lizhen_gitee 1 tháng trước cách đây
mục cha
commit
d027116fb9
100 tập tin đã thay đổi với 12647 bổ sung0 xóa
  1. 7 0
      vendor/autoload.php
  2. 9 0
      vendor/bacon/bacon-qr-code/.gitignore
  3. 15 0
      vendor/bacon/bacon-qr-code/.travis.yml
  4. 22 0
      vendor/bacon/bacon-qr-code/LICENSE
  5. 37 0
      vendor/bacon/bacon-qr-code/Module.php
  6. 24 0
      vendor/bacon/bacon-qr-code/README.md
  7. 43 0
      vendor/bacon/bacon-qr-code/autoload_classmap.php
  8. 12 0
      vendor/bacon/bacon-qr-code/autoload_function.php
  9. 2 0
      vendor/bacon/bacon-qr-code/autoload_register.php
  10. 29 0
      vendor/bacon/bacon-qr-code/composer.json
  11. 115 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php
  12. 435 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php
  13. 350 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php
  14. 51 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php
  15. 134 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php
  16. 65 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php
  17. 101 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php
  18. 62 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php
  19. 236 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php
  20. 70 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php
  21. 476 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php
  22. 687 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php
  23. 64 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php
  24. 158 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php
  25. 687 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php
  26. 291 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php
  27. 580 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php
  28. 201 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php
  29. 14 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php
  30. 14 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php
  31. 14 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php
  32. 14 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php
  33. 14 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php
  34. 14 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php
  35. 160 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php
  36. 37 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php
  37. 84 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php
  38. 148 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php
  39. 338 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php
  40. 63 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php
  41. 210 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php
  42. 152 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php
  43. 115 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php
  44. 61 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php
  45. 146 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php
  46. 26 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php
  47. 91 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php
  48. 150 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php
  49. 105 0
      vendor/bacon/bacon-qr-code/src/BaconQrCode/Writer.php
  50. 201 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitArrayTest.php
  51. 119 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitMatrixTest.php
  52. 30 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitUtilsTest.php
  53. 40 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ErrorCorrectionLevelTest.php
  54. 104 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/FormatInformationTest.php
  55. 42 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ModeTest.php
  56. 111 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ReedSolomonCodecTest.php
  57. 88 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/VersionTest.php
  58. 468 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/EncoderTest.php
  59. 281 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/MaskUtilTest.php
  60. 336 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/MatrixUtilTest.php
  61. 99 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/HtmlTest.php
  62. 149 0
      vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/TextTest.php
  63. 10 0
      vendor/bacon/bacon-qr-code/tests/bootstrap.php
  64. 11 0
      vendor/bacon/bacon-qr-code/tests/phpunit.xml
  65. 23 0
      vendor/bin/carbon
  66. 4 0
      vendor/bin/doctrine-dbal
  67. 98 0
      vendor/bin/patch-type-declarations
  68. 205 0
      vendor/bin/php-parse
  69. 107 0
      vendor/bin/phpunit
  70. 78 0
      vendor/bin/pinyin
  71. 148 0
      vendor/bin/psysh
  72. 576 0
      vendor/bin/sail
  73. 67 0
      vendor/bin/var-dump-server
  74. 49 0
      vendor/bin/yaml-lint
  75. 166 0
      vendor/box/spout/LICENSE
  76. 63 0
      vendor/box/spout/README.md
  77. 89 0
      vendor/box/spout/UPGRADE-3.0.md
  78. 35 0
      vendor/box/spout/appveyor.yml
  79. 43 0
      vendor/box/spout/composer.json
  80. 148 0
      vendor/box/spout/src/Spout/Autoloader/Psr4Autoloader.php
  81. 15 0
      vendor/box/spout/src/Spout/Autoloader/autoload.php
  82. 49 0
      vendor/box/spout/src/Spout/Common/Creator/HelperFactory.php
  83. 216 0
      vendor/box/spout/src/Spout/Common/Entity/Cell.php
  84. 129 0
      vendor/box/spout/src/Spout/Common/Entity/Row.php
  85. 85 0
      vendor/box/spout/src/Spout/Common/Entity/Style/Border.php
  86. 184 0
      vendor/box/spout/src/Spout/Common/Entity/Style/BorderPart.php
  87. 32 0
      vendor/box/spout/src/Spout/Common/Entity/Style/CellAlignment.php
  88. 84 0
      vendor/box/spout/src/Spout/Common/Entity/Style/Color.php
  89. 509 0
      vendor/box/spout/src/Spout/Common/Entity/Style/Style.php
  90. 10 0
      vendor/box/spout/src/Spout/Common/Exception/EncodingConversionException.php
  91. 10 0
      vendor/box/spout/src/Spout/Common/Exception/IOException.php
  92. 10 0
      vendor/box/spout/src/Spout/Common/Exception/InvalidArgumentException.php
  93. 10 0
      vendor/box/spout/src/Spout/Common/Exception/InvalidColorException.php
  94. 12 0
      vendor/box/spout/src/Spout/Common/Exception/SpoutException.php
  95. 10 0
      vendor/box/spout/src/Spout/Common/Exception/UnsupportedTypeException.php
  96. 68 0
      vendor/box/spout/src/Spout/Common/Helper/CellTypeHelper.php
  97. 173 0
      vendor/box/spout/src/Spout/Common/Helper/EncodingHelper.php
  98. 36 0
      vendor/box/spout/src/Spout/Common/Helper/Escaper/CSV.php
  99. 25 0
      vendor/box/spout/src/Spout/Common/Helper/Escaper/EscaperInterface.php
  100. 59 0
      vendor/box/spout/src/Spout/Common/Helper/Escaper/ODS.php

+ 7 - 0
vendor/autoload.php

@@ -0,0 +1,7 @@
+<?php
+
+// autoload.php @generated by Composer
+
+require_once __DIR__ . '/composer/autoload_real.php';
+
+return ComposerAutoloaderInit3b455f97963affcfe9e409ab7f4da960::getLoader();

+ 9 - 0
vendor/bacon/bacon-qr-code/.gitignore

@@ -0,0 +1,9 @@
+composer.lock
+vendor
+nbproject
+.idea
+.buildpath
+.project
+.DS_Store
+.*.sw*
+.*.un~

+ 15 - 0
vendor/bacon/bacon-qr-code/.travis.yml

@@ -0,0 +1,15 @@
+language: php
+php:
+  - 5.3
+  - 5.4
+  - 5.5
+  - 5.6
+  - 7.0
+  - 7.1
+  - hhvm
+
+install:
+  - travis_retry composer install --no-interaction
+  - composer info -i
+
+script: vendor/bin/phpunit --bootstrap tests/bootstrap.php --configuration tests/phpunit.xml tests

+ 22 - 0
vendor/bacon/bacon-qr-code/LICENSE

@@ -0,0 +1,22 @@
+Copyright (c) 2013, Ben 'DASPRiD' Scholzen
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 37 - 0
vendor/bacon/bacon-qr-code/Module.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode;
+
+use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
+
+/**
+ * Module for generating QR codes.
+ */
+class Module implements AutoloaderProviderInterface
+{
+    /**
+     * Get autoloader config.
+     *
+     * @return array
+     */
+    public function getAutoloaderConfig()
+    {
+        return array(
+            'Zend\Loader\ClassMapAutoloader' => array(
+                __DIR__ . '/autoload_classmap.php',
+            ),
+            'Zend\Loader\StandardAutoloader' => array(
+                'namespaces' => array(
+                    __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
+                ),
+            ),
+        );
+    }
+}

+ 24 - 0
vendor/bacon/bacon-qr-code/README.md

@@ -0,0 +1,24 @@
+QR Code generator
+=================
+
+Master: [![Build Status](https://api.travis-ci.org/Bacon/BaconQrCode.png?branch=master)](http://travis-ci.org/Bacon/BaconQrCode)
+
+Introduction
+------------
+BaconQrCode is a port of QR code portion of the ZXing library. It currently
+only features the encoder part, but could later receive the decoder part as
+well.
+
+As the Reed Solomon codec implementation of the ZXing library performs quite
+slow in PHP, it was exchanged with the implementation by Phil Karn.
+
+
+Example usage
+-------------
+```php
+$renderer = new \BaconQrCode\Renderer\Image\Png();
+$renderer->setHeight(256);
+$renderer->setWidth(256);
+$writer = new \BaconQrCode\Writer($renderer);
+$writer->writeFile('Hello World!', 'qrcode.png');
+```

+ 43 - 0
vendor/bacon/bacon-qr-code/autoload_classmap.php

@@ -0,0 +1,43 @@
+<?php
+// Generated by ZF2's ./bin/classmap_generator.php
+return array(
+    'BaconQrCode\Common\AbstractEnum'                         => __DIR__ . '/src/BaconQrCode/Common/AbstractEnum.php',
+    'BaconQrCode\Common\BitArray'                             => __DIR__ . '/src/BaconQrCode/Common/BitArray.php',
+    'BaconQrCode\Common\BitMatrix'                            => __DIR__ . '/src/BaconQrCode/Common/BitMatrix.php',
+    'BaconQrCode\Common\BitUtils'                             => __DIR__ . '/src/BaconQrCode/Common/BitUtils.php',
+    'BaconQrCode\Common\CharacterSetEci'                      => __DIR__ . '/src/BaconQrCode/Common/CharacterSetEci.php',
+    'BaconQrCode\Common\EcBlock'                              => __DIR__ . '/src/BaconQrCode/Common/EcBlock.php',
+    'BaconQrCode\Common\EcBlocks'                             => __DIR__ . '/src/BaconQrCode/Common/EcBlocks.php',
+    'BaconQrCode\Common\ErrorCorrectionLevel'                 => __DIR__ . '/src/BaconQrCode/Common/ErrorCorrectionLevel.php',
+    'BaconQrCode\Common\FormatInformation'                    => __DIR__ . '/src/BaconQrCode/Common/FormatInformation.php',
+    'BaconQrCode\Common\Mode'                                 => __DIR__ . '/src/BaconQrCode/Common/Mode.php',
+    'BaconQrCode\Common\ReedSolomonCodec'                     => __DIR__ . '/src/BaconQrCode/Common/ReedSolomonCodec.php',
+    'BaconQrCode\Common\Version'                              => __DIR__ . '/src/BaconQrCode/Common/Version.php',
+    'BaconQrCode\Encoder\BlockPair'                           => __DIR__ . '/src/BaconQrCode/Encoder/BlockPair.php',
+    'BaconQrCode\Encoder\ByteMatrix'                          => __DIR__ . '/src/BaconQrCode/Encoder/ByteMatrix.php',
+    'BaconQrCode\Encoder\Encoder'                             => __DIR__ . '/src/BaconQrCode/Encoder/Encoder.php',
+    'BaconQrCode\Encoder\MaskUtil'                            => __DIR__ . '/src/BaconQrCode/Encoder/MaskUtil.php',
+    'BaconQrCode\Encoder\MatrixUtil'                          => __DIR__ . '/src/BaconQrCode/Encoder/MatrixUtil.php',
+    'BaconQrCode\Encoder\QrCode'                              => __DIR__ . '/src/BaconQrCode/Encoder/QrCode.php',
+    'BaconQrCode\Exception\ExceptionInterface'                => __DIR__ . '/src/BaconQrCode/Exception/ExceptionInterface.php',
+    'BaconQrCode\Exception\InvalidArgumentException'          => __DIR__ . '/src/BaconQrCode/Exception/InvalidArgumentException.php',
+    'BaconQrCode\Exception\OutOfBoundsException'              => __DIR__ . '/src/BaconQrCode/Exception/OutOfBoundsException.php',
+    'BaconQrCode\Exception\RuntimeException'                  => __DIR__ . '/src/BaconQrCode/Exception/RuntimeException.php',
+    'BaconQrCode\Exception\UnexpectedValueException'          => __DIR__ . '/src/BaconQrCode/Exception/UnexpectedValueException.php',
+    'BaconQrCode\Exception\WriterException'                   => __DIR__ . '/src/BaconQrCode/Exception/WriterException.php',
+    'BaconQrCode\Renderer\Color\Cmyk'                         => __DIR__ . '/src/BaconQrCode/Renderer/Color/Cmyk.php',
+    'BaconQrCode\Renderer\Color\ColorInterface'               => __DIR__ . '/src/BaconQrCode/Renderer/Color/ColorInterface.php',
+    'BaconQrCode\Renderer\Color\Gray'                         => __DIR__ . '/src/BaconQrCode/Renderer/Color/Gray.php',
+    'BaconQrCode\Renderer\Color\Rgb'                          => __DIR__ . '/src/BaconQrCode/Renderer/Color/Rgb.php',
+    'BaconQrCode\Renderer\Image\AbstractRenderer'             => __DIR__ . '/src/BaconQrCode/Renderer/Image/AbstractRenderer.php',
+    'BaconQrCode\Renderer\Image\Decorator\DecoratorInterface' => __DIR__ . '/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php',
+    'BaconQrCode\Renderer\Image\Decorator\FinderPattern'      => __DIR__ . '/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php',
+    'BaconQrCode\Renderer\Image\Eps'                          => __DIR__ . '/src/BaconQrCode/Renderer/Image/Eps.php',
+    'BaconQrCode\Renderer\Image\Png'                          => __DIR__ . '/src/BaconQrCode/Renderer/Image/Png.php',
+    'BaconQrCode\Renderer\Image\RendererInterface'            => __DIR__ . '/src/BaconQrCode/Renderer/Image/RendererInterface.php',
+    'BaconQrCode\Renderer\Image\Svg'                          => __DIR__ . '/src/BaconQrCode/Renderer/Image/Svg.php',
+    'BaconQrCode\Renderer\RendererInterface'                  => __DIR__ . '/src/BaconQrCode/Renderer/RendererInterface.php',
+    'BaconQrCode\Renderer\Text\Plain'                         => __DIR__ . '/src/BaconQrCode/Renderer/Text/Plain.php',
+    'BaconQrCode\Renderer\Text\Html'                          => __DIR__ . '/src/BaconQrCode/Renderer/Text/Html.php',
+    'BaconQrCode\Writer'                                      => __DIR__ . '/src/BaconQrCode/Writer.php',
+);

+ 12 - 0
vendor/bacon/bacon-qr-code/autoload_function.php

@@ -0,0 +1,12 @@
+<?php
+return function ($class) {
+    static $map;
+    if (!$map) {
+        $map = include __DIR__ . '/autoload_classmap.php';
+    }
+
+    if (!isset($map[$class])) {
+        return false;
+    }
+    return include $map[$class];
+};

+ 2 - 0
vendor/bacon/bacon-qr-code/autoload_register.php

@@ -0,0 +1,2 @@
+<?php
+spl_autoload_register(include __DIR__ . '/autoload_function.php');

+ 29 - 0
vendor/bacon/bacon-qr-code/composer.json

@@ -0,0 +1,29 @@
+{
+    "name": "bacon/bacon-qr-code",
+    "description": "BaconQrCode is a QR code generator for PHP.",
+    "license" : "BSD-2-Clause",
+    "homepage": "https://github.com/Bacon/BaconQrCode",
+    "require": {
+        "php": ">=5.3.3",
+        "ext-iconv": "*"
+    },
+    "suggest": {
+        "ext-gd": "to generate QR code images"
+    },
+    "authors": [
+        {
+            "name": "Ben Scholzen 'DASPRiD'",
+            "email": "mail@dasprids.de",
+            "homepage": "http://www.dasprids.de",
+            "role": "Developer"
+        }
+    ],
+    "autoload": {
+        "psr-0": {
+            "BaconQrCode": "src/"
+        }
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^4.8"
+    }
+}

+ 115 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/AbstractEnum.php

@@ -0,0 +1,115 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use BaconQrCode\Exception;
+use ReflectionClass;
+
+/**
+ * A general enum implementation until we got SplEnum.
+ */
+abstract class AbstractEnum
+{
+    /**
+     * Default value.
+     */
+    const __default = null;
+
+    /**
+     * Current value.
+     *
+     * @var mixed
+     */
+    protected $value;
+
+    /**
+     * Cache of constants.
+     *
+     * @var array
+     */
+    protected $constants;
+
+    /**
+     * Whether to handle values strict or not.
+     *
+     * @var boolean
+     */
+    protected $strict;
+
+    /**
+     * Creates a new enum.
+     *
+     * @param mixed   $initialValue
+     * @param boolean $strict
+     */
+    public function __construct($initialValue = null, $strict = false)
+    {
+        $this->strict = $strict;
+        $this->change($initialValue);
+    }
+
+    /**
+     * Changes the value of the enum.
+     *
+     * @param  mixed $value
+     * @return void
+     */
+    public function change($value)
+    {
+        if (!in_array($value, $this->getConstList(), $this->strict)) {
+            throw new Exception\UnexpectedValueException('Value not a const in enum ' . get_class($this));
+        }
+
+        $this->value = $value;
+    }
+
+    /**
+     * Gets current value.
+     *
+     * @return mixed
+     */
+    public function get()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Gets all constants (possible values) as an array.
+     *
+     * @param  boolean $includeDefault
+     * @return array
+     */
+    public function getConstList($includeDefault = true)
+    {
+        if ($this->constants === null) {
+            $reflection      = new ReflectionClass($this);
+            $this->constants = $reflection->getConstants();
+        }
+
+        if ($includeDefault) {
+            return $this->constants;
+        }
+
+        $constants = $this->constants;
+        unset($constants['__default']);
+
+        return $constants;
+    }
+
+    /**
+     * Gets the name of the enum.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return array_search($this->value, $this->getConstList());
+    }
+}

+ 435 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitArray.php

@@ -0,0 +1,435 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use SplFixedArray;
+
+/**
+ * A simple, fast array of bits.
+ */
+class BitArray
+{
+    /**
+     * Bits represented as an array of integers.
+     *
+     * @var SplFixedArray
+     */
+    protected $bits;
+
+    /**
+     * Size of the bit array in bits.
+     *
+     * @var integer
+     */
+    protected $size;
+
+    /**
+     * Creates a new bit array with a given size.
+     *
+     * @param integer $size
+     */
+    public function __construct($size = 0)
+    {
+        $this->size = $size;
+        $this->bits = new SplFixedArray(($this->size + 31) >> 3);
+    }
+
+    /**
+     * Gets the size in bits.
+     *
+     * @return integer
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * Gets the size in bytes.
+     *
+     * @return integer
+     */
+    public function getSizeInBytes()
+    {
+        return ($this->size + 7) >> 3;
+    }
+
+    /**
+     * Ensures that the array has a minimum capacity.
+     *
+     * @param  integer $size
+     * @return void
+     */
+    public function ensureCapacity($size)
+    {
+        if ($size > count($this->bits) << 5) {
+            $this->bits->setSize(($size + 31) >> 5);
+        }
+    }
+
+    /**
+     * Gets a specific bit.
+     *
+     * @param  integer $i
+     * @return boolean
+     */
+    public function get($i)
+    {
+        return ($this->bits[$i >> 5] & (1 << ($i & 0x1f))) !== 0;
+    }
+
+    /**
+     * Sets a specific bit.
+     *
+     * @param  integer $i
+     * @return void
+     */
+    public function set($i)
+    {
+        $this->bits[$i >> 5] = $this->bits[$i >> 5] | 1 << ($i & 0x1f);
+    }
+
+    /**
+     * Flips a specific bit.
+     *
+     * @param  integer $i
+     * @return void
+     */
+    public function flip($i)
+    {
+        $this->bits[$i >> 5] ^= 1 << ($i & 0x1f);
+    }
+
+    /**
+     * Gets the next set bit position from a given position.
+     *
+     * @param  integer $from
+     * @return integer
+     */
+    public function getNextSet($from)
+    {
+        if ($from >= $this->size) {
+            return $this->size;
+        }
+
+        $bitsOffset  = $from >> 5;
+        $currentBits = $this->bits[$bitsOffset];
+        $bitsLength  = count($this->bits);
+
+        $currentBits &= ~((1 << ($from & 0x1f)) - 1);
+
+        while ($currentBits === 0) {
+            if (++$bitsOffset === $bitsLength) {
+                return $this->size;
+            }
+
+            $currentBits = $this->bits[$bitsOffset];
+        }
+
+        $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
+
+        return $result > $this->size ? $this->size : $result;
+    }
+
+    /**
+     * Gets the next unset bit position from a given position.
+     *
+     * @param  integer $from
+     * @return integer
+     */
+    public function getNextUnset($from)
+    {
+        if ($from >= $this->size) {
+            return $this->size;
+        }
+
+        $bitsOffset  = $from >> 5;
+        $currentBits = ~$this->bits[$bitsOffset];
+        $bitsLength  = count($this->bits);
+
+        $currentBits &= ~((1 << ($from & 0x1f)) - 1);
+
+        while ($currentBits === 0) {
+            if (++$bitsOffset === $bitsLength) {
+                return $this->size;
+            }
+
+            $currentBits = ~$this->bits[$bitsOffset];
+        }
+
+        $result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
+
+        return $result > $this->size ? $this->size : $result;
+    }
+
+    /**
+     * Sets a bulk of bits.
+     *
+     * @param  integer $i
+     * @param  integer $newBits
+     * @return void
+     */
+    public function setBulk($i, $newBits)
+    {
+        $this->bits[$i >> 5] = $newBits;
+    }
+
+    /**
+     * Sets a range of bits.
+     *
+     * @param  integer $start
+     * @param  integer $end
+     * @return void
+     * @throws Exception\InvalidArgumentException
+     */
+    public function setRange($start, $end)
+    {
+        if ($end < $start) {
+            throw new Exception\InvalidArgumentException('End must be greater or equal to start');
+        }
+
+        if ($end === $start) {
+            return;
+        }
+
+        $end--;
+
+        $firstInt = $start >> 5;
+        $lastInt  = $end >> 5;
+
+        for ($i = $firstInt; $i <= $lastInt; $i++) {
+            $firstBit = $i > $firstInt ?  0 : $start & 0x1f;
+            $lastBit  = $i < $lastInt ? 31 : $end & 0x1f;
+
+            if ($firstBit === 0 && $lastBit === 31) {
+                $mask = 0x7fffffff;
+            } else {
+                $mask = 0;
+
+                for ($j = $firstBit; $j < $lastBit; $j++) {
+                    $mask |= 1 << $j;
+                }
+            }
+
+            $this->bits[$i] = $this->bits[$i] | $mask;
+        }
+    }
+
+    /**
+     * Clears the bit array, unsetting every bit.
+     *
+     * @return void
+     */
+    public function clear()
+    {
+        $bitsLength = count($this->bits);
+
+        for ($i = 0; $i < $bitsLength; $i++) {
+            $this->bits[$i] = 0;
+        }
+    }
+
+    /**
+     * Checks if a range of bits is set or not set.
+     *
+     * @param  integer $start
+     * @param  integer $end
+     * @param  integer $value
+     * @return boolean
+     * @throws Exception\InvalidArgumentException
+     */
+    public function isRange($start, $end, $value)
+    {
+        if ($end < $start) {
+            throw new Exception\InvalidArgumentException('End must be greater or equal to start');
+        }
+
+        if ($end === $start) {
+            return;
+        }
+
+        $end--;
+
+        $firstInt = $start >> 5;
+        $lastInt  = $end >> 5;
+
+        for ($i = $firstInt; $i <= $lastInt; $i++) {
+            $firstBit = $i > $firstInt ?  0 : $start & 0x1f;
+            $lastBit  = $i < $lastInt ? 31 : $end & 0x1f;
+
+            if ($firstBit === 0 && $lastBit === 31) {
+                $mask = 0x7fffffff;
+            } else {
+                $mask = 0;
+
+                for ($j = $firstBit; $j <= $lastBit; $j++) {
+                    $mask |= 1 << $j;
+                }
+            }
+
+            if (($this->bits[$i] & $mask) !== ($value ? $mask : 0)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Appends a bit to the array.
+     *
+     * @param  boolean $bit
+     * @return void
+     */
+    public function appendBit($bit)
+    {
+        $this->ensureCapacity($this->size + 1);
+
+        if ($bit) {
+            $this->bits[$this->size >> 5] = $this->bits[$this->size >> 5] | (1 << ($this->size & 0x1f));
+        }
+
+        $this->size++;
+    }
+
+    /**
+     * Appends a number of bits (up to 32) to the array.
+     *
+     * @param  integer $value
+     * @param  integer $numBits
+     * @return void
+     * @throws Exception\InvalidArgumentException
+     */
+    public function appendBits($value, $numBits)
+    {
+        if ($numBits < 0 || $numBits > 32) {
+            throw new Exception\InvalidArgumentException('Num bits must be between 0 and 32');
+        }
+
+        $this->ensureCapacity($this->size + $numBits);
+
+        for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) {
+            $this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) === 1);
+        }
+    }
+
+    /**
+     * Appends another bit array to this array.
+     *
+     * @param  BitArray $other
+     * @return void
+     */
+    public function appendBitArray(self $other)
+    {
+        $otherSize = $other->getSize();
+        $this->ensureCapacity($this->size + $other->getSize());
+
+        for ($i = 0; $i < $otherSize; $i++) {
+            $this->appendBit($other->get($i));
+        }
+    }
+
+    /**
+     * Makes an exclusive-or comparision on the current bit array.
+     *
+     * @param  BitArray $other
+     * @return void
+     * @throws Exception\InvalidArgumentException
+     */
+    public function xorBits(self $other)
+    {
+        $bitsLength = count($this->bits);
+        $otherBits  = $other->getBitArray();
+
+        if ($bitsLength !== count($otherBits)) {
+            throw new Exception\InvalidArgumentException('Sizes don\'t match');
+        }
+
+        for ($i = 0; $i < $bitsLength; $i++) {
+            $this->bits[$i] = $this->bits[$i] ^ $otherBits[$i];
+        }
+    }
+
+    /**
+     * Converts the bit array to a byte array.
+     *
+     * @param  integer $bitOffset
+     * @param  integer $numBytes
+     * @return SplFixedArray
+     */
+    public function toBytes($bitOffset, $numBytes)
+    {
+        $bytes = new SplFixedArray($numBytes);
+
+        for ($i = 0; $i < $numBytes; $i++) {
+            $byte = 0;
+
+            for ($j = 0; $j < 8; $j++) {
+                if ($this->get($bitOffset)) {
+                    $byte |= 1 << (7 - $j);
+                }
+
+                $bitOffset++;
+            }
+
+            $bytes[$i] = $byte;
+        }
+
+        return $bytes;
+    }
+
+    /**
+     * Gets the internal bit array.
+     *
+     * @return SplFixedArray
+     */
+    public function getBitArray()
+    {
+        return $this->bits;
+    }
+
+    /**
+     * Reverses the array.
+     *
+     * @return void
+     */
+    public function reverse()
+    {
+        $newBits = new SplFixedArray(count($this->bits));
+
+        for ($i = 0; $i < $this->size; $i++) {
+            if ($this->get($this->size - $i - 1)) {
+                $newBits[$i >> 5] = $newBits[$i >> 5] | (1 << ($i & 0x1f));
+            }
+        }
+
+        $this->bits = newBits;
+    }
+
+    /**
+     * Returns a string representation of the bit array.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $result = '';
+
+        for ($i = 0; $i < $this->size; $i++) {
+            if (($i & 0x07) === 0) {
+                $result .= ' ';
+            }
+
+            $result .= $this->get($i) ? 'X' : '.';
+        }
+
+        return $result;
+    }
+}

+ 350 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitMatrix.php

@@ -0,0 +1,350 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use SplFixedArray;
+
+/**
+ * Bit matrix.
+ *
+ * Represents a 2D matrix of bits. In function arguments below, and throughout
+ * the common module, x is the column position, and y is the row position. The
+ * ordering is always x, y. The origin is at the top-left.
+ */
+class BitMatrix
+{
+    /**
+     * Width of the bit matrix.
+     *
+     * @var integer
+     */
+    protected $width;
+
+    /**
+     * Height of the bit matrix.
+     *
+     * @var integer
+     */
+    protected $height;
+
+    /**
+     * Size in bits of each individual row.
+     *
+     * @var integer
+     */
+    protected $rowSize;
+
+    /**
+     * Bits representation.
+     *
+     * @var SplFixedArray
+     */
+    protected $bits;
+
+    /**
+     * Creates a new bit matrix with given dimensions.
+     *
+     * @param  integer      $width
+     * @param  integer|null $height
+     * @throws Exception\InvalidArgumentException
+     */
+    public function __construct($width, $height = null)
+    {
+        if ($height === null) {
+            $height = $width;
+        }
+
+        if ($width < 1 || $height < 1) {
+            throw new Exception\InvalidArgumentException('Both dimensions must be greater than zero');
+        }
+
+        $this->width   = $width;
+        $this->height  = $height;
+        $this->rowSize = ($width + 31) >> 5;
+        $this->bits    = new SplFixedArray($this->rowSize * $height);
+    }
+
+    /**
+     * Gets the requested bit, where true means black.
+     *
+     * @param  integer $x
+     * @param  integer $y
+     * @return boolean
+     */
+    public function get($x, $y)
+    {
+        $offset = $y * $this->rowSize + ($x >> 5);
+        return (BitUtils::unsignedRightShift($this->bits[$offset], ($x & 0x1f)) & 1) !== 0;
+    }
+
+    /**
+     * Sets the given bit to true.
+     *
+     * @param  integer $x
+     * @param  integer $y
+     * @return void
+     */
+    public function set($x, $y)
+    {
+        $offset = $y * $this->rowSize + ($x >> 5);
+        $this->bits[$offset] = $this->bits[$offset] | (1 << ($x & 0x1f));
+    }
+
+    /**
+     * Flips the given bit.
+     *
+     * @param  integer $x
+     * @param  integer $y
+     * @return void
+     */
+    public function flip($x, $y)
+    {
+        $offset = $y * $this->rowSize + ($x >> 5);
+        $this->bits[$offset] = $this->bits[$offset] ^ (1 << ($x & 0x1f));
+    }
+
+    /**
+     * Clears all bits (set to false).
+     *
+     * @return void
+     */
+    public function clear()
+    {
+        $max = count($this->bits);
+
+        for ($i = 0; $i < $max; $i++) {
+            $this->bits[$i] = 0;
+        }
+    }
+
+    /**
+     * Sets a square region of the bit matrix to true.
+     *
+     * @param  integer $left
+     * @param  integer $top
+     * @param  integer $width
+     * @param  integer $height
+     * @return void
+     */
+    public function setRegion($left, $top, $width, $height)
+    {
+        if ($top < 0 || $left < 0) {
+            throw new Exception\InvalidArgumentException('Left and top must be non-negative');
+        }
+
+        if ($height < 1 || $width < 1) {
+            throw new Exception\InvalidArgumentException('Width and height must be at least 1');
+        }
+
+        $right  = $left + $width;
+        $bottom = $top + $height;
+
+        if ($bottom > $this->height || $right > $this->width) {
+            throw new Exception\InvalidArgumentException('The region must fit inside the matrix');
+        }
+
+        for ($y = $top; $y < $bottom; $y++) {
+            $offset = $y * $this->rowSize;
+
+            for ($x = $left; $x < $right; $x++) {
+                $index = $offset + ($x >> 5);
+                $this->bits[$index] = $this->bits[$index] | (1 << ($x & 0x1f));
+            }
+        }
+    }
+
+    /**
+     * A fast method to retrieve one row of data from the matrix as a BitArray.
+     *
+     * @param  integer  $y
+     * @param  BitArray $row
+     * @return BitArray
+     */
+    public function getRow($y, BitArray $row = null)
+    {
+        if ($row === null || $row->getSize() < $this->width) {
+            $row = new BitArray($this->width);
+        }
+
+        $offset = $y * $this->rowSize;
+
+        for ($x = 0; $x < $this->rowSize; $x++) {
+            $row->setBulk($x << 5, $this->bits[$offset + $x]);
+        }
+
+        return $row;
+    }
+
+    /**
+     * Sets a row of data from a BitArray.
+     *
+     * @param  integer  $y
+     * @param  BitArray $row
+     * @return void
+     */
+    public function setRow($y, BitArray $row)
+    {
+        $bits = $row->getBitArray();
+
+        for ($i = 0; $i < $this->rowSize; $i++) {
+            $this->bits[$y * $this->rowSize + $i] = $bits[$i];
+        }
+    }
+
+    /**
+     * This is useful in detecting the enclosing rectangle of a 'pure' barcode.
+     *
+     * @return SplFixedArray
+     */
+    public function getEnclosingRectangle()
+    {
+        $left   = $this->width;
+        $top    = $this->height;
+        $right  = -1;
+        $bottom = -1;
+
+        for ($y = 0; $y < $this->height; $y++) {
+            for ($x32 = 0; $x32 < $this->rowSize; $x32++) {
+                $bits = $this->bits[$y * $this->rowSize + $x32];
+
+                if ($bits !== 0) {
+                    if ($y < $top) {
+                        $top = $y;
+                    }
+
+                    if ($y > $bottom) {
+                        $bottom = $y;
+                    }
+
+                    if ($x32 * 32 < $left) {
+                        $bit = 0;
+
+                        while (($bits << (31 - $bit)) === 0) {
+                            $bit++;
+                        }
+
+                        if (($x32 * 32 + $bit) < $left) {
+                            $left = $x32 * 32 + $bit;
+                        }
+                    }
+                }
+
+                if ($x32 * 32 + 31 > $right) {
+                    $bit = 31;
+
+                    while (BitUtils::unsignedRightShift($bits, $bit) === 0) {
+                        $bit--;
+                    }
+
+                    if (($x32 * 32 + $bit) > $right) {
+                        $right = $x32 * 32 + $bit;
+                    }
+                }
+            }
+        }
+
+        $width  = $right - $left;
+        $height = $bottom - $top;
+
+        if ($width < 0 || $height < 0) {
+            return null;
+        }
+
+        return SplFixedArray::fromArray(array($left, $top, $width, $height), false);
+    }
+
+    /**
+     * Gets the most top left set bit.
+     *
+     * This is useful in detecting a corner of a 'pure' barcode.
+     *
+     * @return SplFixedArray
+     */
+    public function getTopLeftOnBit()
+    {
+        $bitsOffset = 0;
+
+        while ($bitsOffset < count($this->bits) && $this->bits[$bitsOffset] === 0) {
+            $bitsOffset++;
+        }
+
+        if ($bitsOffset === count($this->bits)) {
+            return null;
+        }
+
+        $x = intval($bitsOffset / $this->rowSize);
+        $y = ($bitsOffset % $this->rowSize) << 5;
+
+        $bits = $this->bits[$bitsOffset];
+        $bit  = 0;
+
+        while (($bits << (31 - $bit)) === 0) {
+            $bit++;
+        }
+
+        $x += $bit;
+
+        return SplFixedArray::fromArray(array($x, $y), false);
+    }
+
+    /**
+     * Gets the most bottom right set bit.
+     *
+     * This is useful in detecting a corner of a 'pure' barcode.
+     *
+     * @return SplFixedArray
+     */
+    public function getBottomRightOnBit()
+    {
+        $bitsOffset = count($this->bits) - 1;
+
+        while ($bitsOffset >= 0 && $this->bits[$bitsOffset] === 0) {
+            $bitsOffset--;
+        }
+
+        if ($bitsOffset < 0) {
+            return null;
+        }
+
+        $x = intval($bitsOffset / $this->rowSize);
+        $y = ($bitsOffset % $this->rowSize) << 5;
+
+        $bits = $this->bits[$bitsOffset];
+        $bit  = 0;
+
+        while (BitUtils::unsignedRightShift($bits, $bit) === 0) {
+            $bit--;
+        }
+
+        $x += $bit;
+
+        return SplFixedArray::fromArray(array($x, $y), false);
+    }
+
+    /**
+     * Gets the width of the matrix,
+     *
+     * @return integer
+     */
+    public function getWidth()
+    {
+        return $this->width;
+    }
+
+    /**
+     * Gets the height of the matrix.
+     *
+     * @return integer
+     */
+    public function getHeight()
+    {
+        return $this->height;
+    }
+}

+ 51 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/BitUtils.php

@@ -0,0 +1,51 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+/**
+ * General bit utilities.
+ *
+ * All utility methods are based on 32-bit integers and also work on 64-bit
+ * systems.
+ */
+class BitUtils
+{
+    /**
+     * Performs an unsigned right shift.
+     *
+     * This is the same as the unsigned right shift operator ">>>" in other
+     * languages.
+     *
+     * @param  integer $a
+     * @param  integer $b
+     * @return integer
+     */
+    public static function unsignedRightShift($a, $b)
+    {
+        return (
+            $a >= 0
+            ? $a >> $b
+            : (($a & 0x7fffffff) >> $b) | (0x40000000 >> ($b - 1))
+        );
+    }
+
+    /**
+     * Gets the number of trailing zeros.
+     *
+     * @param  integer $i
+     * @return integer
+     */
+    public static function numberOfTrailingZeros($i)
+    {
+        $lastPos = strrpos(str_pad(decbin($i), 32, '0', STR_PAD_LEFT), '1');
+
+        return $lastPos === false ? 32 : 31 - $lastPos;
+    }
+}

+ 134 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/CharacterSetEci.php

@@ -0,0 +1,134 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+/**
+ * Encapsulates a Character Set ECI, according to "Extended Channel
+ * Interpretations" 5.3.1.1 of ISO 18004.
+ */
+class CharacterSetEci extends AbstractEnum
+{
+    /**#@+
+     * Character set constants.
+     */
+    const CP437                = 0;
+    const ISO8859_1            = 1;
+    const ISO8859_2            = 4;
+    const ISO8859_3            = 5;
+    const ISO8859_4            = 6;
+    const ISO8859_5            = 7;
+    const ISO8859_6            = 8;
+    const ISO8859_7            = 9;
+    const ISO8859_8            = 10;
+    const ISO8859_9            = 11;
+    const ISO8859_10           = 12;
+    const ISO8859_11           = 13;
+    const ISO8859_12           = 14;
+    const ISO8859_13           = 15;
+    const ISO8859_14           = 16;
+    const ISO8859_15           = 17;
+    const ISO8859_16           = 18;
+    const SJIS                 = 20;
+    const CP1250               = 21;
+    const CP1251               = 22;
+    const CP1252               = 23;
+    const CP1256               = 24;
+    const UNICODE_BIG_UNMARKED = 25;
+    const UTF8                 = 26;
+    const ASCII                = 27;
+    const BIG5                 = 28;
+    const GB18030              = 29;
+    const EUC_KR               = 30;
+    /**#@-*/
+
+    /**
+     * Map between character names and their ECI values.
+     *
+     * @var array
+     */
+    protected static $nameToEci = array(
+        'ISO-8859-1'   => self::ISO8859_1,
+        'ISO-8859-2'   => self::ISO8859_2,
+        'ISO-8859-3'   => self::ISO8859_3,
+        'ISO-8859-4'   => self::ISO8859_4,
+        'ISO-8859-5'   => self::ISO8859_5,
+        'ISO-8859-6'   => self::ISO8859_6,
+        'ISO-8859-7'   => self::ISO8859_7,
+        'ISO-8859-8'   => self::ISO8859_8,
+        'ISO-8859-9'   => self::ISO8859_9,
+        'ISO-8859-10'  => self::ISO8859_10,
+        'ISO-8859-11'  => self::ISO8859_11,
+        'ISO-8859-12'  => self::ISO8859_12,
+        'ISO-8859-13'  => self::ISO8859_13,
+        'ISO-8859-14'  => self::ISO8859_14,
+        'ISO-8859-15'  => self::ISO8859_15,
+        'ISO-8859-16'  => self::ISO8859_16,
+        'SHIFT-JIS'    => self::SJIS,
+        'WINDOWS-1250' => self::CP1250,
+        'WINDOWS-1251' => self::CP1251,
+        'WINDOWS-1252' => self::CP1252,
+        'WINDOWS-1256' => self::CP1256,
+        'UTF-16BE'     => self::UNICODE_BIG_UNMARKED,
+        'UTF-8'        => self::UTF8,
+        'ASCII'        => self::ASCII,
+        'GBK'          => self::GB18030,
+        'EUC-KR'       => self::EUC_KR,
+    );
+
+    /**
+     * Additional possible values for character sets.
+     *
+     * @var array
+     */
+    protected $additionalValues = array(
+        self::CP437 => 2,
+        self::ASCII => 170,
+    );
+
+    /**
+     * Gets character set ECI by value.
+     *
+     * @param  string $name
+     * @return CharacterSetEci|null
+     */
+    public static function getCharacterSetECIByValue($value)
+    {
+        if ($value < 0 || $value >= 900) {
+            throw new Exception\InvalidArgumentException('Value must be between 0 and 900');
+        }
+
+        if (false !== ($key = array_search($value, self::$additionalValues))) {
+            $value = $key;
+        }
+
+        try {
+            return new self($value);
+        } catch (Exception\UnexpectedValueException $e) {
+            return null;
+        }
+    }
+
+    /**
+     * Gets character set ECI by name.
+     *
+     * @param  string $name
+     * @return CharacterSetEci|null
+     */
+    public static function getCharacterSetECIByName($name)
+    {
+        $name = strtoupper($name);
+
+        if (isset(self::$nameToEci[$name])) {
+            return new self(self::$nameToEci[$name]);
+        }
+
+        return null;
+    }
+}

+ 65 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlock.php

@@ -0,0 +1,65 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+/**
+ * Encapsualtes the parameters for one error-correction block in one symbol
+ * version. This includes the number of data codewords, and the number of times
+ * a block with these parameters is used consecutively in the QR code version's
+ * format.
+ */
+class EcBlock
+{
+    /**
+     * How many times the block is used.
+     *
+     * @var integer
+     */
+    protected $count;
+
+    /**
+     * Number of data codewords.
+     *
+     * @var integer
+     */
+    protected $dataCodewords;
+
+    /**
+     * Creates a new EC block.
+     *
+     * @param integer $count
+     * @param integer $dataCodewords
+     */
+    public function __construct($count, $dataCodewords)
+    {
+        $this->count         = $count;
+        $this->dataCodewords = $dataCodewords;
+    }
+
+    /**
+     * Returns how many times the block is used.
+     *
+     * @return integer
+     */
+    public function getCount()
+    {
+        return $this->count;
+    }
+
+    /**
+     * Returns the number of data codewords.
+     *
+     * @return integer
+     */
+    public function getDataCodewords()
+    {
+        return $this->dataCodewords;
+    }
+}

+ 101 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/EcBlocks.php

@@ -0,0 +1,101 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use SplFixedArray;
+
+/**
+ * Encapsulates a set of error-correction blocks in one symbol version. Most
+ * versions will use blocks of differing sizes within one version, so, this
+ * encapsulates the parameters for each set of blocks. It also holds the number
+ * of error-correction codewords per block since it will be the same across all
+ * blocks within one version.
+ */
+class EcBlocks
+{
+    /**
+     * Number of EC codewords per block.
+     *
+     * @var integer
+     */
+    protected $ecCodewordsPerBlock;
+
+    /**
+     * List of EC blocks.
+     *
+     * @var SplFixedArray
+     */
+    protected $ecBlocks;
+
+    /**
+     * Creates a new EC blocks instance.
+     *
+     * @param integer      $ecCodewordsPerBlock
+     * @param EcBlock      $ecb1
+     * @param EcBlock|null $ecb2
+     */
+    public function __construct($ecCodewordsPerBlock, EcBlock $ecb1, EcBlock $ecb2 = null)
+    {
+        $this->ecCodewordsPerBlock = $ecCodewordsPerBlock;
+
+        $this->ecBlocks = new SplFixedArray($ecb2 === null ? 1 : 2);
+        $this->ecBlocks[0] = $ecb1;
+
+        if ($ecb2 !== null) {
+            $this->ecBlocks[1] = $ecb2;
+        }
+    }
+
+    /**
+     * Gets the number of EC codewords per block.
+     *
+     * @return integer
+     */
+    public function getEcCodewordsPerBlock()
+    {
+        return $this->ecCodewordsPerBlock;
+    }
+
+    /**
+     * Gets the total number of EC block appearances.
+     *
+     * @return integer
+     */
+    public function getNumBlocks()
+    {
+        $total = 0;
+
+        foreach ($this->ecBlocks as $ecBlock) {
+            $total += $ecBlock->getCount();
+        }
+
+        return $total;
+    }
+
+    /**
+     * Gets the total count of EC codewords.
+     *
+     * @return integer
+     */
+    public function getTotalEcCodewords()
+    {
+        return $this->ecCodewordsPerBlock * $this->getNumBlocks();
+    }
+
+    /**
+     * Gets the EC blocks included in this collection.
+     *
+     * @return SplFixedArray
+     */
+    public function getEcBlocks()
+    {
+        return $this->ecBlocks;
+    }
+}

+ 62 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ErrorCorrectionLevel.php

@@ -0,0 +1,62 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+/**
+ * Enum representing the four error correction levels.
+ */
+class ErrorCorrectionLevel extends AbstractEnum
+{
+    /**
+     * Level L, ~7% correction.
+     */
+    const L = 0x1;
+
+    /**
+     * Level M, ~15% correction.
+     */
+    const M = 0x0;
+
+    /**
+     * Level Q, ~25% correction.
+     */
+    const Q = 0x3;
+
+    /**
+     * Level H, ~30% correction.
+     */
+    const H = 0x2;
+
+    /**
+     * Gets the ordinal of this enumeration constant.
+     *
+     * @return integer
+     */
+    public function getOrdinal()
+    {
+        switch ($this->value) {
+            case self::L:
+                return 0;
+                break;
+
+            case self::M:
+                return 1;
+                break;
+
+            case self::Q:
+                return 2;
+                break;
+
+            case self::H:
+                return 3;
+                break;
+        }
+    }
+}

+ 236 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/FormatInformation.php

@@ -0,0 +1,236 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+/**
+ * Encapsulates a QR Code's format information, including the data mask used and
+ * error correction level.
+ */
+class FormatInformation
+{
+    /**
+     * Mask for format information.
+     */
+    const FORMAT_INFO_MASK_QR = 0x5412;
+
+    /**
+     * Lookup table for decoding format information.
+     *
+     * See ISO 18004:2006, Annex C, Table C.1
+     *
+     * @var array
+     */
+    protected static $formatInfoDecodeLookup = array(
+        array(0x5412, 0x00),
+        array(0x5125, 0x01),
+        array(0x5e7c, 0x02),
+        array(0x5b4b, 0x03),
+        array(0x45f9, 0x04),
+        array(0x40ce, 0x05),
+        array(0x4f97, 0x06),
+        array(0x4aa0, 0x07),
+        array(0x77c4, 0x08),
+        array(0x72f3, 0x09),
+        array(0x7daa, 0x0a),
+        array(0x789d, 0x0b),
+        array(0x662f, 0x0c),
+        array(0x6318, 0x0d),
+        array(0x6c41, 0x0e),
+        array(0x6976, 0x0f),
+        array(0x1689, 0x10),
+        array(0x13be, 0x11),
+        array(0x1ce7, 0x12),
+        array(0x19d0, 0x13),
+        array(0x0762, 0x14),
+        array(0x0255, 0x15),
+        array(0x0d0c, 0x16),
+        array(0x083b, 0x17),
+        array(0x355f, 0x18),
+        array(0x3068, 0x19),
+        array(0x3f31, 0x1a),
+        array(0x3a06, 0x1b),
+        array(0x24b4, 0x1c),
+        array(0x2183, 0x1d),
+        array(0x2eda, 0x1e),
+        array(0x2bed, 0x1f),
+    );
+
+    /**
+     * Offset i holds the number of 1 bits in the binary representation of i.
+     *
+     * @var array
+     */
+    protected static $bitsSetInHalfByte = array(0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4);
+
+    /**
+     * Error correction level.
+     *
+     * @var ErrorCorrectionLevel
+     */
+    protected $ecLevel;
+
+    /**
+     * Data mask.
+     *
+     * @var integer
+     */
+    protected $dataMask;
+
+    /**
+     * Creates a new format information instance.
+     *
+     * @param integer $formatInfo
+     */
+    protected function __construct($formatInfo)
+    {
+        $this->ecLevel  = new ErrorCorrectionLevel(($formatInfo >> 3) & 0x3);
+        $this->dataMask = $formatInfo & 0x7;
+    }
+
+    /**
+     * Checks how many bits are different between two integers.
+     *
+     * @param  integer $a
+     * @param  integer $b
+     * @return integer
+     */
+    public static function numBitsDiffering($a, $b)
+    {
+        $a ^= $b;
+
+        return (
+            self::$bitsSetInHalfByte[$a & 0xf]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 4) & 0xf)]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 8) & 0xf)]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 12) & 0xf)]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 16) & 0xf)]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 20) & 0xf)]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 24) & 0xf)]
+            + self::$bitsSetInHalfByte[(BitUtils::unsignedRightShift($a, 28) & 0xf)]
+        );
+    }
+
+    /**
+     * Decodes format information.
+     *
+     * @param  integer $maskedFormatInfo1
+     * @param  integer $maskedFormatInfo2
+     * @return FormatInformation|null
+     */
+    public static function decodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2)
+    {
+        $formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2);
+
+        if ($formatInfo !== null) {
+            return $formatInfo;
+        }
+
+        // Should return null, but, some QR codes apparently do not mask this
+        // info. Try again by actually masking the pattern first.
+        return self::doDecodeFormatInformation(
+            $maskedFormatInfo1 ^ self::FORMAT_INFO_MASK_QR,
+            $maskedFormatInfo2 ^ self::FORMAT_INFO_MASK_QR
+        );
+    }
+
+    /**
+     * Internal method for decoding format information.
+     *
+     * @param  integer $maskedFormatInfo1
+     * @param  integer $maskedFormatInfo2
+     * @return FormatInformation|null
+     */
+    protected static function doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2)
+    {
+        $bestDifference = PHP_INT_MAX;
+        $bestFormatInfo = 0;
+
+        foreach (self::$formatInfoDecodeLookup as $decodeInfo) {
+            $targetInfo = $decodeInfo[0];
+
+            if ($targetInfo === $maskedFormatInfo1 || $targetInfo === $maskedFormatInfo2) {
+                // Found an exact match
+                return new self($decodeInfo[1]);
+            }
+
+            $bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo);
+
+            if ($bitsDifference < $bestDifference) {
+                $bestFormatInfo = $decodeInfo[1];
+                $bestDifference = $bitsDifference;
+            }
+
+            if ($maskedFormatInfo1 !== $maskedFormatInfo2) {
+                // Also try the other option
+                $bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo);
+
+                if ($bitsDifference < $bestDifference) {
+                    $bestFormatInfo = $decodeInfo[1];
+                    $bestDifference = $bitsDifference;
+                }
+            }
+        }
+
+        // Hamming distance of the 32 masked codes is 7, by construction, so
+        // <= 3 bits differing means we found a match.
+        if ($bestDifference <= 3) {
+            return new self($bestFormatInfo);
+        }
+
+        return null;
+    }
+
+    /**
+     * Gets the error correction level.
+     *
+     * @return ErrorCorrectionLevel
+     */
+    public function getErrorCorrectionLevel()
+    {
+        return $this->ecLevel;
+    }
+
+    /**
+     * Gets the data mask.
+     *
+     * @return integer
+     */
+    public function getDataMask()
+    {
+        return $this->dataMask;
+    }
+
+    /**
+     * Hashes the code of the EC level.
+     *
+     * @return integer
+     */
+    public function hashCode()
+    {
+        return ($this->ecLevel->get() << 3) | $this->dataMask;
+    }
+
+    /**
+     * Verifies if this instance equals another one.
+     *
+     * @param  mixed $other
+     * @return boolean
+     */
+    public function equals($other) {
+        if (!$other instanceof self) {
+            return false;
+        }
+
+        return (
+            $this->ecLevel->get() === $other->getErrorCorrectionLevel()->get()
+            && $this->dataMask === $other->getDataMask()
+        );
+    }
+}

+ 70 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Mode.php

@@ -0,0 +1,70 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+/**
+ * Enum representing various modes in which data can be encoded to bits.
+ */
+class Mode extends AbstractEnum
+{
+    /**#@+
+     * Mode constants.
+     */
+    const TERMINATOR           = 0x0;
+    const NUMERIC              = 0x1;
+    const ALPHANUMERIC         = 0x2;
+    const STRUCTURED_APPEND    = 0x3;
+    const BYTE                 = 0x4;
+    const ECI                  = 0x7;
+    const KANJI                = 0x8;
+    const FNC1_FIRST_POSITION  = 0x5;
+    const FNC1_SECOND_POSITION = 0x9;
+    const HANZI                = 0xd;
+    /**#@-*/
+
+    /**
+     * Character count bits for each version.
+     *
+     * @var array
+     */
+    protected static $characterCountBitsForVersions = array(
+        self::TERMINATOR           => array(0, 0, 0),
+        self::NUMERIC              => array(10, 12, 14),
+        self::ALPHANUMERIC         => array(9, 11, 13),
+        self::STRUCTURED_APPEND    => array(0, 0, 0),
+        self::BYTE                 => array(8, 16, 16),
+        self::ECI                  => array(0, 0, 0),
+        self::KANJI                => array(8, 10, 12),
+        self::FNC1_FIRST_POSITION  => array(0, 0, 0),
+        self::FNC1_SECOND_POSITION => array(0, 0, 0),
+        self::HANZI                => array(8, 10, 12),
+    );
+
+    /**
+     * Gets the number of bits used in a specific QR code version.
+     *
+     * @param  Version $version
+     * @return integer
+     */
+    public function getCharacterCountBits(Version $version)
+    {
+        $number = $version->getVersionNumber();
+
+        if ($number <= 9) {
+            $offset = 0;
+        } elseif ($number <= 26) {
+            $offset = 1;
+        } else {
+            $offset = 2;
+        }
+
+        return self::$characterCountBitsForVersions[$this->value][$offset];
+    }
+}

+ 476 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/ReedSolomonCodec.php

@@ -0,0 +1,476 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use BaconQrCode\Exception;
+use SplFixedArray;
+
+/**
+ * Reed-Solomon codec for 8-bit characters.
+ *
+ * Based on libfec by Phil Karn, KA9Q.
+ */
+class ReedSolomonCodec
+{
+    /**
+     * Symbol size in bits.
+     *
+     * @var integer
+     */
+    protected $symbolSize;
+
+    /**
+     * Block size in symbols.
+     *
+     * @var integer
+     */
+    protected $blockSize;
+
+    /**
+     * First root of RS code generator polynomial, index form.
+     *
+     * @var integer
+     */
+    protected $firstRoot;
+
+    /**
+     * Primitive element to generate polynomial roots, index form.
+     *
+     * @var integer
+     */
+    protected $primitive;
+
+    /**
+     * Prim-th root of 1, index form.
+     *
+     * @var integer
+     */
+    protected $iPrimitive;
+
+    /**
+     * RS code generator polynomial degree (number of roots).
+     *
+     * @var integer
+     */
+    protected $numRoots;
+
+    /**
+     * Padding bytes at front of shortened block.
+     *
+     * @var integer
+     */
+    protected $padding;
+
+    /**
+     * Log lookup table.
+     *
+     * @var SplFixedArray
+     */
+    protected $alphaTo;
+
+    /**
+     * Anti-Log lookup table.
+     *
+     * @var SplFixedArray
+     */
+    protected $indexOf;
+
+    /**
+     * Generator polynomial.
+     *
+     * @var SplFixedArray
+     */
+    protected $generatorPoly;
+
+    /**
+     * Creates a new reed solomon instance.
+     *
+     * @param  integer $symbolSize
+     * @param  integer $gfPoly
+     * @param  integer $firstRoot
+     * @param  integer $primitive
+     * @param  integer $numRoots
+     * @param  integer $padding
+     * @throws Exception\InvalidArgumentException
+     * @throws Exception\RuntimeException
+     */
+    public function __construct($symbolSize, $gfPoly, $firstRoot, $primitive, $numRoots, $padding)
+    {
+        if ($symbolSize < 0 || $symbolSize > 8) {
+            throw new Exception\InvalidArgumentException('Symbol size must be between 0 and 8');
+        }
+
+        if ($firstRoot < 0 || $firstRoot >= (1 << $symbolSize)) {
+            throw new Exception\InvalidArgumentException('First root must be between 0 and ' . (1 << $symbolSize));
+        }
+
+        if ($numRoots < 0 || $numRoots >= (1 << $symbolSize)) {
+            throw new Exception\InvalidArgumentException('Num roots must be between 0 and ' . (1 << $symbolSize));
+        }
+
+        if ($padding < 0 || $padding >= ((1 << $symbolSize) - 1 - $numRoots)) {
+            throw new Exception\InvalidArgumentException('Padding must be between 0 and ' . ((1 << $symbolSize) - 1 - $numRoots));
+        }
+
+        $this->symbolSize = $symbolSize;
+        $this->blockSize  = (1 << $symbolSize) - 1;
+        $this->padding    = $padding;
+        $this->alphaTo    = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
+        $this->indexOf    = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
+
+        // Generate galous field lookup table
+        $this->indexOf[0]                = $this->blockSize;
+        $this->alphaTo[$this->blockSize] = 0;
+
+        $sr = 1;
+
+        for ($i = 0; $i < $this->blockSize; $i++) {
+            $this->indexOf[$sr] = $i;
+            $this->alphaTo[$i]  = $sr;
+
+            $sr <<= 1;
+
+            if ($sr & (1 << $symbolSize)) {
+                $sr ^= $gfPoly;
+            }
+
+            $sr &= $this->blockSize;
+        }
+
+        if ($sr !== 1) {
+            throw new Exception\RuntimeException('Field generator polynomial is not primitive');
+        }
+
+        // Form RS code generator polynomial from its roots
+        $this->generatorPoly = SplFixedArray::fromArray(array_fill(0, $numRoots + 1, 0), false);
+        $this->firstRoot     = $firstRoot;
+        $this->primitive     = $primitive;
+        $this->numRoots      = $numRoots;
+
+        // Find prim-th root of 1, used in decoding
+        for ($iPrimitive = 1; ($iPrimitive % $primitive) !== 0; $iPrimitive += $this->blockSize);
+        $this->iPrimitive = intval($iPrimitive / $primitive);
+
+        $this->generatorPoly[0] = 1;
+
+        for ($i = 0, $root = $firstRoot * $primitive; $i < $numRoots; $i++, $root += $primitive) {
+            $this->generatorPoly[$i + 1] = 1;
+
+            for ($j = $i; $j > 0; $j--) {
+                if ($this->generatorPoly[$j] !== 0) {
+                    $this->generatorPoly[$j] = $this->generatorPoly[$j - 1] ^ $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[$j]] + $root)];
+                } else {
+                    $this->generatorPoly[$j] = $this->generatorPoly[$j - 1];
+                }
+            }
+
+            $this->generatorPoly[$j] = $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[0]] + $root)];
+        }
+
+        // Convert generator poly to index form for quicker encoding
+        for ($i = 0; $i <= $numRoots; $i++) {
+            $this->generatorPoly[$i] = $this->indexOf[$this->generatorPoly[$i]];
+        }
+    }
+
+    /**
+     * Encodes data and writes result back into parity array.
+     *
+     * @param  SplFixedArray $data
+     * @param  SplFixedArray $parity
+     * @return void
+     */
+    public function encode(SplFixedArray $data, SplFixedArray $parity)
+    {
+        for ($i = 0; $i < $this->numRoots; $i++) {
+            $parity[$i] = 0;
+        }
+
+        $iterations = $this->blockSize - $this->numRoots - $this->padding;
+
+        for ($i = 0; $i < $iterations; $i++) {
+            $feedback = $this->indexOf[$data[$i] ^ $parity[0]];
+
+            if ($feedback !== $this->blockSize) {
+                // Feedback term is non-zero
+                $feedback = $this->modNn($this->blockSize - $this->generatorPoly[$this->numRoots] + $feedback);
+
+                for ($j = 1; $j < $this->numRoots; $j++) {
+                    $parity[$j] = $parity[$j] ^ $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[$this->numRoots - $j])];
+                }
+            }
+
+            for ($j = 0; $j < $this->numRoots - 1; $j++) {
+                $parity[$j] = $parity[$j + 1];
+            }
+
+            if ($feedback !== $this->blockSize) {
+                $parity[$this->numRoots - 1] = $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[0])];
+            } else {
+                $parity[$this->numRoots - 1] = 0;
+            }
+        }
+    }
+
+    /**
+     * Decodes received data.
+     *
+     * @param  SplFixedArray      $data
+     * @param  SplFixedArray|null $erasures
+     * @return null|integer
+     */
+    public function decode(SplFixedArray $data, SplFixedArray $erasures = null)
+    {
+        // This speeds up the initialization a bit.
+        $numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0), false);
+        $numRoots        = SplFixedArray::fromArray(array_fill(0, $this->numRoots, 0), false);
+
+        $lambda    = clone $numRootsPlusOne;
+        $b         = clone $numRootsPlusOne;
+        $t         = clone $numRootsPlusOne;
+        $omega     = clone $numRootsPlusOne;
+        $root      = clone $numRoots;
+        $loc       = clone $numRoots;
+
+        $numErasures = ($erasures !== null ? count($erasures) : 0);
+
+        // Form the Syndromes; i.e., evaluate data(x) at roots of g(x)
+        $syndromes = SplFixedArray::fromArray(array_fill(0, $this->numRoots, $data[0]), false);
+
+        for ($i = 1; $i < $this->blockSize - $this->padding; $i++) {
+            for ($j = 0; $j < $this->numRoots; $j++) {
+                if ($syndromes[$j] === 0) {
+                    $syndromes[$j] = $data[$i];
+                } else {
+                    $syndromes[$j] = $data[$i] ^ $this->alphaTo[
+                        $this->modNn($this->indexOf[$syndromes[$j]] + ($this->firstRoot + $j) * $this->primitive)
+                    ];
+                }
+            }
+        }
+
+        // Convert syndromes to index form, checking for nonzero conditions
+        $syndromeError = 0;
+
+        for ($i = 0; $i < $this->numRoots; $i++) {
+            $syndromeError |= $syndromes[$i];
+            $syndromes[$i]  = $this->indexOf[$syndromes[$i]];
+        }
+
+        if (!$syndromeError) {
+            // If syndrome is zero, data[] is a codeword and there are no errors
+            // to correct, so return data[] unmodified.
+            return 0;
+        }
+
+        $lambda[0] = 1;
+
+        if ($numErasures > 0) {
+            // Init lambda to be the erasure locator polynomial
+            $lambda[1] = $this->alphaTo[$this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[0]))];
+
+            for ($i = 1; $i < $numErasures; $i++) {
+                $u = $this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[$i]));
+
+                for ($j = $i + 1; $j > 0; $j--) {
+                    $tmp = $this->indexOf[$lambda[$j - 1]];
+
+                    if ($tmp !== $this->blockSize) {
+                        $lambda[$j] = $lambda[$j] ^ $this->alphaTo[$this->modNn($u + $tmp)];
+                    }
+                }
+            }
+        }
+
+        for ($i = 0; $i <= $this->numRoots; $i++) {
+            $b[$i] = $this->indexOf[$lambda[$i]];
+        }
+
+        // Begin Berlekamp-Massey algorithm to determine error+erasure locator
+        // polynomial
+        $r  = $numErasures;
+        $el = $numErasures;
+
+        while (++$r <= $this->numRoots) {
+            // Compute discrepancy at the r-th step in poly form
+            $discrepancyR = 0;
+
+            for ($i = 0; $i < $r; $i++) {
+                if ($lambda[$i] !== 0 && $syndromes[$r - $i - 1] !== $this->blockSize) {
+                    $discrepancyR ^= $this->alphaTo[$this->modNn($this->indexOf[$lambda[$i]] + $syndromes[$r - $i - 1])];
+                }
+            }
+
+            $discrepancyR = $this->indexOf[$discrepancyR];
+
+            if ($discrepancyR === $this->blockSize) {
+                $tmp = $b->toArray();
+                array_unshift($tmp, $this->blockSize);
+                array_pop($tmp);
+                $b = SplFixedArray::fromArray($tmp, false);
+            } else {
+                $t[0] = $lambda[0];
+
+                for ($i = 0; $i < $this->numRoots; $i++) {
+                    if ($b[$i] !== $this->blockSize) {
+                        $t[$i + 1] = $lambda[$i + 1] ^ $this->alphaTo[$this->modNn($discrepancyR + $b[$i])];
+                    } else {
+                        $t[$i + 1] = $lambda[$i + 1];
+                    }
+                }
+
+                if (2 * $el <= $r + $numErasures - 1) {
+                    $el = $r + $numErasures - $el;
+
+                    for ($i = 0; $i <= $this->numRoots; $i++) {
+                        $b[$i] = (
+                            $lambda[$i] === 0
+                            ? $this->blockSize
+                            : $this->modNn($this->indexOf[$lambda[$i]] - $discrepancyR + $this->blockSize)
+                        );
+                    }
+                } else {
+                    $tmp = $b->toArray();
+                    array_unshift($tmp, $this->blockSize);
+                    array_pop($tmp);
+                    $b = SplFixedArray::fromArray($tmp, false);
+                }
+
+                $lambda = clone $t;
+            }
+        }
+
+        // Convert lambda to index form and compute deg(lambda(x))
+        $degLambda = 0;
+
+        for ($i = 0; $i <= $this->numRoots; $i++) {
+            $lambda[$i] = $this->indexOf[$lambda[$i]];
+
+            if ($lambda[$i] !== $this->blockSize) {
+                $degLambda = $i;
+            }
+        }
+
+        // Find roots of the error+erasure locator polynomial by Chien search.
+        $reg    = clone $lambda;
+        $reg[0] = 0;
+        $count  = 0;
+
+        for ($i = 1, $k = $this->iPrimitive - 1; $i <= $this->blockSize; $i++, $k = $this->modNn($k + $this->iPrimitive)) {
+            $q = 1;
+
+            for ($j = $degLambda; $j > 0; $j--) {
+                if ($reg[$j] !== $this->blockSize) {
+                    $reg[$j]  = $this->modNn($reg[$j] + $j);
+                    $q       ^= $this->alphaTo[$reg[$j]];
+                }
+            }
+
+            if ($q !== 0) {
+                // Not a root
+                continue;
+            }
+
+            // Store root (index-form) and error location number
+            $root[$count] = $i;
+            $loc[$count]  = $k;
+
+            if (++$count === $degLambda) {
+                break;
+            }
+        }
+
+        if ($degLambda !== $count) {
+            // deg(lambda) unequal to number of roots: uncorreactable error
+            // detected
+            return null;
+        }
+
+        // Compute err+eras evaluate poly omega(x) = s(x)*lambda(x) (modulo
+        // x**numRoots). In index form. Also find deg(omega).
+        $degOmega = $degLambda - 1;
+
+        for ($i = 0; $i <= $degOmega; $i++) {
+            $tmp = 0;
+
+            for ($j = $i; $j >= 0; $j--) {
+                if ($syndromes[$i - $j] !== $this->blockSize && $lambda[$j] !== $this->blockSize) {
+                    $tmp ^= $this->alphaTo[$this->modNn($syndromes[$i - $j] + $lambda[$j])];
+                }
+            }
+
+            $omega[$i] = $this->indexOf[$tmp];
+        }
+
+        // Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
+        // inv(X(l))**(firstRoot-1) and den = lambda_pr(inv(X(l))) all in poly
+        // form.
+        for ($j = $count - 1; $j >= 0; $j--) {
+            $num1 = 0;
+
+            for ($i = $degOmega; $i >= 0; $i--) {
+                if ($omega[$i] !== $this->blockSize) {
+                    $num1 ^= $this->alphaTo[$this->modNn($omega[$i] + $i * $root[$j])];
+                }
+            }
+
+            $num2 = $this->alphaTo[$this->modNn($root[$j] * ($this->firstRoot - 1) + $this->blockSize)];
+            $den  = 0;
+
+            // lambda[i+1] for i even is the formal derivativelambda_pr of
+            // lambda[i]
+            for ($i = min($degLambda, $this->numRoots - 1) & ~1; $i >= 0; $i -= 2) {
+                if ($lambda[$i + 1] !== $this->blockSize) {
+                    $den ^= $this->alphaTo[$this->modNn($lambda[$i + 1] + $i * $root[$j])];
+                }
+            }
+
+            // Apply error to data
+            if ($num1 !== 0 && $loc[$j] >= $this->padding) {
+                $data[$loc[$j] - $this->padding] = $data[$loc[$j] - $this->padding] ^ (
+                    $this->alphaTo[
+                        $this->modNn(
+                            $this->indexOf[$num1] + $this->indexOf[$num2] + $this->blockSize - $this->indexOf[$den]
+                        )
+                    ]
+                );
+            }
+        }
+
+        if ($erasures !== null) {
+            if (count($erasures) < $count) {
+                $erasures->setSize($count);
+            }
+
+            for ($i = 0; $i < $count; $i++) {
+                $erasures[$i] = $loc[$i];
+            }
+        }
+
+        return $count;
+    }
+
+    /**
+     * Computes $x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, without a slow
+     * divide.
+     *
+     * @param  itneger $x
+     * @return integer
+     */
+    protected function modNn($x)
+    {
+        while ($x >= $this->blockSize) {
+            $x -= $this->blockSize;
+            $x  = ($x >> $this->symbolSize) + ($x & $this->blockSize);
+        }
+
+        return $x;
+    }
+}

+ 687 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Common/Version.php

@@ -0,0 +1,687 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use SplFixedArray;
+
+/**
+ * Version representation.
+ */
+class Version
+{
+    /**
+     * Version decode information.
+     *
+     * @var array
+     */
+    protected static $versionDecodeInfo = array(
+        0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
+        0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
+        0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
+        0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
+        0x27541, 0x28c69
+    );
+
+    /**
+     * Cached version instances.
+     *
+     * @var array
+     */
+    protected static $versions = array();
+
+    /**
+     * Version number of this version.
+     *
+     * @var integer
+     */
+    protected $versionNumber;
+
+    /**
+     * Alignment pattern centers.
+     *
+     * @var SplFixedArray
+     */
+    protected $alignmentPatternCenters;
+
+    /**
+     * Error correction blocks.
+     *
+     * @var SplFixedArray
+     */
+    protected $errorCorrectionBlocks;
+
+    /**
+     * Total number of codewords.
+     *
+     * @var integer
+     */
+    protected $totalCodewords;
+
+    /**
+     * Creates a new version.
+     *
+     * @param integer       $versionNumber
+     * @param SplFixedArray $alignmentPatternCenters
+     * @param SplFixedArray $ecBlocks
+     */
+    protected function __construct(
+        $versionNumber,
+        SplFixedArray $alignmentPatternCenters,
+        SplFixedArray $ecBlocks
+    ) {
+        $this->versionNumber           = $versionNumber;
+        $this->alignmentPatternCenters = $alignmentPatternCenters;
+        $this->errorCorrectionBlocks   = $ecBlocks;
+
+        $totalCodewords = 0;
+        $ecCodewords    = $ecBlocks[0]->getEcCodewordsPerBlock();
+
+        foreach ($ecBlocks[0]->getEcBlocks() as $ecBlock) {
+            $totalCodewords += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords);
+        }
+
+        $this->totalCodewords = $totalCodewords;
+    }
+
+    /**
+     * Gets the version number.
+     *
+     * @return integer
+     */
+    public function getVersionNumber()
+    {
+        return $this->versionNumber;
+    }
+
+    /**
+     * Gets the alignment pattern centers.
+     *
+     * @return SplFixedArray
+     */
+    public function getAlignmentPatternCenters()
+    {
+        return $this->alignmentPatternCenters;
+    }
+
+    /**
+     * Gets the total number of codewords.
+     *
+     * @return integer
+     */
+    public function getTotalCodewords()
+    {
+        return $this->totalCodewords;
+    }
+
+    /**
+     * Gets the dimension for the current version.
+     *
+     * @return integer
+     */
+    public function getDimensionForVersion()
+    {
+        return 17 + 4 * $this->versionNumber;
+    }
+
+    /**
+     * Gets the number of EC blocks for a specific EC level.
+     *
+     * @param  ErrorCorrectionLevel $ecLevel
+     * @return integer
+     */
+    public function getEcBlocksForLevel(ErrorCorrectionLevel $ecLevel)
+    {
+        return $this->errorCorrectionBlocks[$ecLevel->getOrdinal()];
+    }
+
+    /**
+     * Gets a provisional version number for a specific dimension.
+     *
+     * @param  integer $dimension
+     * @return Version
+     * @throws Exception\InvalidArgumentException
+     */
+    public static function getProvisionalVersionForDimension($dimension)
+    {
+        if ($dimension % 4 !== 1) {
+            throw new Exception\InvalidArgumentException('Dimension is not 1 mod 4');
+        }
+
+        return self::getVersionForNumber(($dimension - 17) >> 2);
+    }
+
+    /**
+     * Gets a version instance for a specific version number.
+     *
+     * @param  integer $versionNumber
+     * @return Version
+     * @throws Exception\InvalidArgumentException
+     */
+    public static function getVersionForNumber($versionNumber)
+    {
+        if ($versionNumber < 1 || $versionNumber > 40) {
+            throw new Exception\InvalidArgumentException('Version number must be between 1 and 40');
+        }
+
+        if (!isset(self::$versions[$versionNumber])) {
+            self::buildVersion($versionNumber);
+        }
+
+        return self::$versions[$versionNumber - 1];
+    }
+
+    /**
+     * Decodes version information from an integer and returns the version.
+     *
+     * @param  integer $versionBits
+     * @return Version|null
+     */
+    public static function decodeVersionInformation($versionBits)
+    {
+        $bestDifference = PHP_INT_MAX;
+        $bestVersion    = 0;
+
+        foreach (self::$versionDecodeInfo as $i => $targetVersion) {
+            if ($targetVersion === $versionBits) {
+                return self::getVersionForNumber($i + 7);
+            }
+
+            $bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion);
+
+            if ($bitsDifference < $bestDifference) {
+                $bestVersion    = $i + 7;
+                $bestDifference = $bitsDifference;
+            }
+        }
+
+        if ($bestDifference <= 3) {
+            return self::getVersionForNumber($bestVersion);
+        }
+
+        return null;
+    }
+
+    /**
+     * Builds the function pattern for the current version.
+     *
+     * @return BitMatrix
+     */
+    public function buildFunctionPattern()
+    {
+        $dimension = $this->getDimensionForVersion();
+        $bitMatrix = new BitMatrix($dimension);
+
+        // Top left finder pattern + separator + format
+        $bitMatrix->setRegion(0, 0, 9, 9);
+        // Top right finder pattern + separator + format
+        $bitMatrix->setRegion($dimension - 8, 0, 8, 9);
+        // Bottom left finder pattern + separator + format
+        $bitMatrix->setRegion(0, $dimension - 8, 9, 8);
+
+        // Alignment patterns
+        $max = count($this->alignmentPatternCenters);
+
+        for ($x = 0; $x < $max; $x++) {
+            $i = $this->alignmentPatternCenters[$x] - 2;
+
+            for ($y = 0; $y < $max; $y++) {
+                if (($x === 0 && ($y === 0 || $y === $max - 1)) || ($x === $max - 1 && $y === 0)) {
+                    // No alignment patterns near the three finder paterns
+                    continue;
+                }
+
+                $bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5);
+            }
+        }
+
+        // Vertical timing pattern
+        $bitMatrix->setRegion(6, 9, 1, $dimension - 17);
+        // Horizontal timing pattern
+        $bitMatrix->setRegion(9, 6, $dimension - 17, 1);
+
+        if ($this->versionNumber > 6) {
+            // Version info, top right
+            $bitMatrix->setRegion($dimension - 11, 0, 3, 6);
+            // Version info, bottom left
+            $bitMatrix->setRegion(0, $dimension - 11, 6, 3);
+        }
+
+        return $bitMatrix;
+    }
+
+    /**
+     * Returns a string representation for the version.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return (string) $this->versionNumber;
+    }
+
+    /**
+     * Build and cache a specific version.
+     *
+     * See ISO 18004:2006 6.5.1 Table 9.
+     *
+     * @param  integer $versionNumber
+     * @return void
+     */
+    protected static function buildVersion($versionNumber)
+    {
+        switch ($versionNumber) {
+            case 1:
+                $patterns = array();
+                $ecBlocks = array(
+                    new EcBlocks(7, new EcBlock(1, 19)),
+                    new EcBlocks(10, new EcBlock(1, 16)),
+                    new EcBlocks(13, new EcBlock(1, 13)),
+                    new EcBlocks(17, new EcBlock(1, 9)),
+                );
+                break;
+
+            case 2:
+                $patterns = array(6, 18);
+                $ecBlocks = array(
+                    new EcBlocks(10, new EcBlock(1, 34)),
+                    new EcBlocks(16, new EcBlock(1, 28)),
+                    new EcBlocks(22, new EcBlock(1, 22)),
+                    new EcBlocks(28, new EcBlock(1, 16)),
+                );
+                break;
+
+            case 3:
+                $patterns = array(6, 22);
+                $ecBlocks = array(
+                    new EcBlocks(15, new EcBlock(1, 55)),
+                    new EcBlocks(26, new EcBlock(1, 44)),
+                    new EcBlocks(18, new EcBlock(2, 17)),
+                    new EcBlocks(22, new EcBlock(2, 13)),
+                );
+                break;
+
+            case 4:
+                $patterns = array(6, 26);
+                $ecBlocks = array(
+                    new EcBlocks(20, new EcBlock(1, 80)),
+                    new EcBlocks(18, new EcBlock(2, 32)),
+                    new EcBlocks(26, new EcBlock(3, 24)),
+                    new EcBlocks(16, new EcBlock(4, 9)),
+                );
+                break;
+
+            case 5:
+                $patterns = array(6, 30);
+                $ecBlocks = array(
+                    new EcBlocks(26, new EcBlock(1, 108)),
+                    new EcBlocks(24, new EcBlock(2, 43)),
+                    new EcBlocks(18, new EcBlock(2, 15), new EcBlock(2, 16)),
+                    new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12)),
+                );
+                break;
+
+            case 6:
+                $patterns = array(6, 34);
+                $ecBlocks = array(
+                    new EcBlocks(18, new EcBlock(2, 68)),
+                    new EcBlocks(16, new EcBlock(4, 27)),
+                    new EcBlocks(24, new EcBlock(4, 19)),
+                    new EcBlocks(28, new EcBlock(4, 15)),
+                );
+                break;
+
+            case 7:
+                $patterns = array(6, 22, 38);
+                $ecBlocks = array(
+                    new EcBlocks(20, new EcBlock(2, 78)),
+                    new EcBlocks(18, new EcBlock(4, 31)),
+                    new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)),
+                    new EcBlocks(26, new EcBlock(4, 13)),
+                );
+                break;
+
+            case 8:
+                $patterns = array(6, 24, 42);
+                $ecBlocks = array(
+                    new EcBlocks(24, new EcBlock(2, 97)),
+                    new EcBlocks(22, new EcBlock(2, 38), new EcBlock(2, 39)),
+                    new EcBlocks(22, new EcBlock(4, 18), new EcBlock(2, 19)),
+                    new EcBlocks(26, new EcBlock(4, 14), new EcBlock(2, 15)),
+                );
+                break;
+
+            case 9:
+                $patterns = array(6, 26, 46);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(2, 116)),
+                    new EcBlocks(22, new EcBlock(3, 36), new EcBlock(2, 37)),
+                    new EcBlocks(20, new EcBlock(4, 16), new EcBlock(4, 17)),
+                    new EcBlocks(24, new EcBlock(4, 12), new EcBlock(4, 13)),
+                );
+                break;
+
+            case 10:
+                $patterns = array(6, 28, 50);
+                $ecBlocks = array(
+                    new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)),
+                    new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)),
+                    new EcBlocks(24, new EcBlock(6, 19), new EcBlock(2, 20)),
+                    new EcBlocks(28, new EcBlock(6, 15), new EcBlock(2, 16)),
+                );
+                break;
+
+            case 11:
+                $patterns = array(6, 30, 54);
+                $ecBlocks = array(
+                    new EcBlocks(20, new EcBlock(4, 81)),
+                    new EcBlocks(30, new EcBlock(1, 50), new EcBlock(4, 51)),
+                    new EcBlocks(28, new EcBlock(4, 22), new EcBlock(4, 23)),
+                    new EcBlocks(24, new EcBlock(3, 12), new EcBlock(8, 13)),
+                );
+                break;
+
+            case 12:
+                $patterns = array(6, 32, 58);
+                $ecBlocks = array(
+                    new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)),
+                    new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)),
+                    new EcBlocks(26, new EcBlock(4, 20), new EcBlock(6, 21)),
+                    new EcBlocks(28, new EcBlock(7, 14), new EcBlock(4, 15)),
+                );
+                break;
+
+            case 13:
+                $patterns = array(6, 34, 62);
+                $ecBlocks = array(
+                    new EcBlocks(26, new EcBlock(4, 107)),
+                    new EcBlocks(22, new EcBlock(8, 37), new EcBlock(1, 38)),
+                    new EcBlocks(24, new EcBlock(8, 20), new EcBlock(4, 21)),
+                    new EcBlocks(22, new EcBlock(12, 11), new EcBlock(4, 12)),
+                );
+                break;
+
+            case 14:
+                $patterns = array(6, 26, 46, 66);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1, 116)),
+                    new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5, 41)),
+                    new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5, 17)),
+                    new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13)),
+                );
+                break;
+
+            case 15:
+                $patterns = array(6, 26, 48, 70);
+                $ecBlocks = array(
+                    new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)),
+                    new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)),
+                    new EcBlocks(30, new EcBlock(5, 24), new EcBlock(7, 25)),
+                    new EcBlocks(24, new EcBlock(11, 12), new EcBlock(7, 13)),
+                );
+                break;
+
+            case 16:
+                $patterns = array(6, 26, 50, 74);
+                $ecBlocks = array(
+                    new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)),
+                    new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)),
+                    new EcBlocks(24, new EcBlock(15, 19), new EcBlock(2, 20)),
+                    new EcBlocks(30, new EcBlock(3, 15), new EcBlock(13, 16)),
+                );
+                break;
+
+            case 17:
+                $patterns = array(6, 30, 54, 78);
+                $ecBlocks = array(
+                    new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5, 108)),
+                    new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1, 47)),
+                    new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15, 23)),
+                    new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15)),
+                );
+                break;
+
+            case 18:
+                $patterns = array(6, 30, 56, 82);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1, 121)),
+                    new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4, 44)),
+                    new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1, 23)),
+                    new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15)),
+                );
+                break;
+
+            case 19:
+                $patterns = array(6, 30, 58, 86);
+                $ecBlocks = array(
+                    new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4, 114)),
+                    new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11, 45)),
+                    new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4, 22)),
+                    new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14)),
+                );
+                break;
+
+            case 20:
+                $patterns = array(6, 34, 62, 90);
+                $ecBlocks = array(
+                    new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5, 108)),
+                    new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13, 42)),
+                    new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5, 25)),
+                    new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16)),
+                );
+                break;
+
+            case 21:
+                $patterns = array(6, 28, 50, 72, 94);
+                $ecBlocks = array(
+                    new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4, 117)),
+                    new EcBlocks(26, new EcBlock(17, 42)),
+                    new EcBlocks(28, new EcBlock(17, 22), new EcBlock(6, 23)),
+                    new EcBlocks(30, new EcBlock(19, 16), new EcBlock(6, 17)),
+                );
+                break;
+
+            case 22:
+                $patterns = array(6, 26, 50, 74, 98);
+                $ecBlocks = array(
+                    new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7, 112)),
+                    new EcBlocks(28, new EcBlock(17, 46)),
+                    new EcBlocks(30, new EcBlock(7, 24), new EcBlock(16, 25)),
+                    new EcBlocks(24, new EcBlock(34, 13)),
+                );
+                break;
+
+            case 23:
+                $patterns = array(6, 30, 54, 78, 102);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5, 122)),
+                    new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14, 48)),
+                    new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14, 25)),
+                    new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16)),
+                );
+                break;
+
+            case 24:
+                $patterns = array(6, 28, 54, 80, 106);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4, 118)),
+                    new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14, 46)),
+                    new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16, 25)),
+                    new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17)),
+                );
+                break;
+
+            case 25:
+                $patterns = array(6, 32, 58, 84, 110);
+                $ecBlocks = array(
+                    new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4, 107)),
+                    new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13, 48)),
+                    new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22, 25)),
+                    new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16)),
+                );
+                break;
+
+            case 26:
+                $patterns = array(6, 30, 58, 86, 114);
+                $ecBlocks = array(
+                    new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2, 115)),
+                    new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4, 47)),
+                    new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6, 23)),
+                    new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17)),
+                );
+                break;
+
+            case 27:
+                $patterns = array(6, 34, 62, 90, 118);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4, 123)),
+                    new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3, 46)),
+                    new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26, 24)),
+                    new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16)),
+                );
+                break;
+
+            case 28:
+                $patterns = array(6, 26, 50, 74, 98, 122);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10, 118)),
+                    new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23, 46)),
+                    new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31, 25)),
+                    new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16)),
+                );
+                break;
+
+            case 29:
+                $patterns = array(6, 30, 54, 78, 102, 126);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7, 117)),
+                    new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7, 46)),
+                    new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37, 24)),
+                    new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16)),
+                );
+                break;
+
+            case 30:
+                $patterns = array(6, 26, 52, 78, 104, 130);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10, 116)),
+                    new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10, 48)),
+                    new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25, 25)),
+                    new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16)),
+                );
+                break;
+
+            case 31:
+                $patterns = array(6, 30, 56, 82, 108, 134);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3, 116)),
+                    new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29, 47)),
+                    new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1, 25)),
+                    new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16)),
+                );
+                break;
+
+            case 32:
+                $patterns = array(6, 34, 60, 86, 112, 138);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(17, 115)),
+                    new EcBlocks(28, new EcBlock(10, 46), new EcBlock(23, 47)),
+                    new EcBlocks(30, new EcBlock(10, 24), new EcBlock(35, 25)),
+                    new EcBlocks(30, new EcBlock(19, 15), new EcBlock(35, 16)),
+                );
+                break;
+
+            case 33:
+                $patterns = array(6, 30, 58, 86, 114, 142);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1, 116)),
+                    new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21, 47)),
+                    new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19, 25)),
+                    new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16)),
+                );
+                break;
+
+            case 34:
+                $patterns = array(6, 34, 62, 90, 118, 146);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6, 116)),
+                    new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23, 47)),
+                    new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7, 25)),
+                    new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17)),
+                );
+                break;
+
+            case 35:
+                $patterns = array(6, 30, 54, 78, 102, 126, 150);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7, 122)),
+                    new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26, 48)),
+                    new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14, 25)),
+                    new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16)),
+                );
+                break;
+
+            case 36:
+                $patterns = array(6, 24, 50, 76, 102, 128, 154);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14, 122)),
+                    new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34, 48)),
+                    new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10, 25)),
+                    new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16)),
+                );
+                break;
+
+            case 37:
+                $patterns = array(6, 28, 54, 80, 106, 132, 158);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4, 123)),
+                    new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14, 47)),
+                    new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10, 25)),
+                    new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16)),
+                );
+                break;
+
+            case 38:
+                $patterns = array(6, 32, 58, 84, 110, 136, 162);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18, 123)),
+                    new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32, 47)),
+                    new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14, 25)),
+                    new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16)),
+                );
+                break;
+
+            case 39:
+                $patterns = array(6, 26, 54, 82, 110, 138, 166);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4, 118)),
+                    new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7, 48)),
+                    new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22, 25)),
+                    new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16)),
+                );
+                break;
+
+            case 40:
+                $patterns = array(6, 30, 58, 86, 114, 142, 170);
+                $ecBlocks = array(
+                    new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6, 119)),
+                    new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31, 48)),
+                    new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34, 25)),
+                    new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16)),
+                );
+                break;
+        }
+
+        self::$versions[$versionNumber - 1] = new self(
+            $versionNumber,
+            SplFixedArray::fromArray($patterns, false),
+            SplFixedArray::fromArray($ecBlocks, false)
+        );
+    }
+}

+ 64 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/BlockPair.php

@@ -0,0 +1,64 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use SplFixedArray;
+
+/**
+ * Block pair.
+ */
+class BlockPair
+{
+    /**
+     * Data bytes in the block.
+     *
+     * @var SplFixedArray
+     */
+    protected $dataBytes;
+
+    /**
+     * Error correction bytes in the block.
+     *
+     * @var SplFixedArray
+     */
+    protected $errorCorrectionBytes;
+
+    /**
+     * Creates a new block pair.
+     *
+     * @param SplFixedArray $data
+     * @param SplFixedArray $errorCorrection
+     */
+    public function __construct(SplFixedArray $data, SplFixedArray $errorCorrection)
+    {
+        $this->dataBytes            = $data;
+        $this->errorCorrectionBytes = $errorCorrection;
+    }
+
+    /**
+     * Gets the data bytes.
+     *
+     * @return SplFixedArray
+     */
+    public function getDataBytes()
+    {
+        return $this->dataBytes;
+    }
+
+    /**
+     * Gets the error correction bytes.
+     *
+     * @return SplFixedArray
+     */
+    public function getErrorCorrectionBytes()
+    {
+        return $this->errorCorrectionBytes;
+    }
+}

+ 158 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/ByteMatrix.php

@@ -0,0 +1,158 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use SplFixedArray;
+
+/**
+ * Byte matrix.
+ */
+class ByteMatrix
+{
+    /**
+     * Bytes in the matrix, represented as array.
+     *
+     * @var SplFixedArray
+     */
+    protected $bytes;
+
+    /**
+     * Width of the matrix.
+     *
+     * @var integer
+     */
+    protected $width;
+
+    /**
+     * Height of the matrix.
+     *
+     * @var integer
+     */
+    protected $height;
+
+    /**
+     * Creates a new byte matrix.
+     *
+     * @param  integer $width
+     * @param  integer $height
+     */
+    public function __construct($width, $height)
+    {
+        $this->height = $height;
+        $this->width  = $width;
+        $this->bytes  = new SplFixedArray($height);
+
+        for ($y = 0; $y < $height; $y++) {
+            $this->bytes[$y] = new SplFixedArray($width);
+        }
+    }
+
+    /**
+     * Gets the width of the matrix.
+     *
+     * @return integer
+     */
+    public function getWidth()
+    {
+        return $this->width;
+    }
+
+    /**
+     * Gets the height of the matrix.
+     *
+     * @return integer
+     */
+    public function getHeight()
+    {
+        return $this->height;
+    }
+
+    /**
+     * Gets the internal representation of the matrix.
+     *
+     * @return SplFixedArray
+     */
+    public function getArray()
+    {
+        return $this->bytes;
+    }
+
+    /**
+     * Gets the byte for a specific position.
+     *
+     * @param  integer $x
+     * @param  integer $y
+     * @return integer
+     */
+    public function get($x, $y)
+    {
+        return $this->bytes[$y][$x];
+    }
+
+    /**
+     * Sets the byte for a specific position.
+     *
+     * @param  integer $x
+     * @param  integer $y
+     * @param  integer $value
+     * @return void
+     */
+    public function set($x, $y, $value)
+    {
+        $this->bytes[$y][$x] = (int) $value;
+    }
+
+    /**
+     * Clears the matrix with a specific value.
+     *
+     * @param  integer $value
+     * @return void
+     */
+    public function clear($value)
+    {
+        for ($y = 0; $y < $this->height; $y++) {
+            for ($x = 0; $x < $this->width; $x++) {
+                $this->bytes[$y][$x] = $value;
+            }
+        }
+    }
+
+    /**
+     * Returns a string representation of the matrix.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $result = '';
+
+        for ($y = 0; $y < $this->height; $y++) {
+            for ($x = 0; $x < $this->width; $x++) {
+                switch ($this->bytes[$y][$x]) {
+                    case 0:
+                        $result .= ' 0';
+                        break;
+
+                    case 1:
+                        $result .= ' 1';
+                        break;
+
+                    default:
+                        $result .= '  ';
+                        break;
+                }
+            }
+
+            $result .= "\n";
+        }
+
+        return $result;
+    }
+}

+ 687 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/Encoder.php

@@ -0,0 +1,687 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\BitArray;
+use BaconQrCode\Common\CharacterSetEci;
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Common\Mode;
+use BaconQrCode\Common\ReedSolomonCodec;
+use BaconQrCode\Common\Version;
+use BaconQrCode\Exception;
+use SplFixedArray;
+
+/**
+ * Encoder.
+ */
+class Encoder
+{
+    /**
+     * Default byte encoding.
+     */
+    const DEFAULT_BYTE_MODE_ECODING = 'ISO-8859-1';
+
+    /**
+     * The original table is defined in the table 5 of JISX0510:2004 (p.19).
+     *
+     * @var array
+     */
+    protected static $alphanumericTable = array(
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  // 0x00-0x0f
+        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,  // 0x10-0x1f
+        36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,  // 0x20-0x2f
+        0,   1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,  // 0x30-0x3f
+        -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,  // 0x40-0x4f
+        25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,  // 0x50-0x5f
+    );
+
+    /**
+     * Codec cache.
+     *
+     * @var array
+     */
+    protected static $codecs = array();
+
+    /**
+     * Encodes "content" with the error correction level "ecLevel".
+     *
+     * @param  string               $content
+     * @param  ErrorCorrectionLevel $ecLevel
+     * @param  ?                    $hints
+     * @return QrCode
+     */
+    public static function encode($content, ErrorCorrectionLevel $ecLevel, $encoding = self::DEFAULT_BYTE_MODE_ECODING)
+    {
+        // Pick an encoding mode appropriate for the content. Note that this
+        // will not attempt to use multiple modes / segments even if that were
+        // more efficient. Would be nice.
+        $mode = self::chooseMode($content, $encoding);
+
+        // This will store the header information, like mode and length, as well
+        // as "header" segments like an ECI segment.
+        $headerBits = new BitArray();
+
+        // Append ECI segment if applicable
+        if ($mode->get() === Mode::BYTE && $encoding !== self::DEFAULT_BYTE_MODE_ECODING) {
+            $eci = CharacterSetEci::getCharacterSetEciByName($encoding);
+
+            if ($eci !== null) {
+                self::appendEci($eci, $headerBits);
+            }
+        }
+
+        // (With ECI in place,) Write the mode marker
+        self::appendModeInfo($mode, $headerBits);
+
+        // Collect data within the main segment, separately, to count its size
+        // if needed. Don't add it to main payload yet.
+        $dataBits = new BitArray();
+        self::appendBytes($content, $mode, $dataBits, $encoding);
+
+        // Hard part: need to know version to know how many bits length takes.
+        // But need to know how many bits it takes to know version. First we
+        // take a guess at version by assuming version will be the minimum, 1:
+        $provisionalBitsNeeded = $headerBits->getSize()
+                               + $mode->getCharacterCountBits(Version::getVersionForNumber(1))
+                               + $dataBits->getSize();
+        $provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel);
+
+        // Use that guess to calculate the right version. I am still not sure
+        // this works in 100% of cases.
+        $bitsNeeded = $headerBits->getSize()
+                    + $mode->getCharacterCountBits($provisionalVersion)
+                    + $dataBits->getSize();
+        $version = self::chooseVersion($bitsNeeded, $ecLevel);
+
+        $headerAndDataBits = new BitArray();
+        $headerAndDataBits->appendBitArray($headerBits);
+
+        // Find "length" of main segment and write it.
+        $numLetters = ($mode->get() === Mode::BYTE ? $dataBits->getSizeInBytes() : strlen($content));
+        self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits);
+
+        // Put data together into the overall payload.
+        $headerAndDataBits->appendBitArray($dataBits);
+        $ecBlocks     = $version->getEcBlocksForLevel($ecLevel);
+        $numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords();
+
+        // Terminate the bits properly.
+        self::terminateBits($numDataBytes, $headerAndDataBits);
+
+        // Interleave data bits with error correction code.
+        $finalBits = self::interleaveWithEcBytes(
+            $headerAndDataBits,
+            $version->getTotalCodewords(),
+            $numDataBytes,
+            $ecBlocks->getNumBlocks()
+        );
+
+        $qrCode = new QrCode();
+        $qrCode->setErrorCorrectionLevel($ecLevel);
+        $qrCode->setMode($mode);
+        $qrCode->setVersion($version);
+
+        // Choose the mask pattern and set to "qrCode".
+        $dimension   = $version->getDimensionForVersion();
+        $matrix      = new ByteMatrix($dimension, $dimension);
+        $maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix);
+        $qrCode->setMaskPattern($maskPattern);
+
+        // Build the matrix and set it to "qrCode".
+        MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix);
+        $qrCode->setMatrix($matrix);
+
+        return $qrCode;
+    }
+
+    /**
+     * Gets the alphanumeric code for a byte.
+     *
+     * @param  string|integer $code
+     * @return integer
+     */
+    protected static function getAlphanumericCode($code)
+    {
+        $code = (is_string($code) ? ord($code) : $code);
+
+        if (isset(self::$alphanumericTable[$code])) {
+            return self::$alphanumericTable[$code];
+        }
+
+        return -1;
+    }
+
+    /**
+     * Chooses the best mode for a given content.
+     *
+     * @param  string $content
+     * @param  string $encoding
+     * @return Mode
+     */
+    protected static function chooseMode($content, $encoding = null)
+    {
+        if (strcasecmp($encoding, 'SHIFT-JIS') === 0) {
+            return self::isOnlyDoubleByteKanji($content) ? new Mode(Mode::KANJI) : new Mode(Mode::BYTE);
+        }
+
+        $hasNumeric      = false;
+        $hasAlphanumeric = false;
+        $contentLength   = strlen($content);
+
+        for ($i = 0; $i < $contentLength; $i++) {
+            $char = $content[$i];
+
+            if (ctype_digit($char)) {
+                $hasNumeric = true;
+            } elseif (self::getAlphanumericCode($char) !== -1) {
+                $hasAlphanumeric = true;
+            } else {
+                return new Mode(Mode::BYTE);
+            }
+        }
+
+        if ($hasAlphanumeric) {
+            return new Mode(Mode::ALPHANUMERIC);
+        } elseif ($hasNumeric) {
+            return new Mode(Mode::NUMERIC);
+        }
+
+        return new Mode(Mode::BYTE);
+    }
+
+    /**
+     * Calculates the mask penalty for a matrix.
+     *
+     * @param  ByteMatrix $matrix
+     * @return integer
+     */
+    protected static function calculateMaskPenalty(ByteMatrix $matrix)
+    {
+        return (
+            MaskUtil::applyMaskPenaltyRule1($matrix)
+            + MaskUtil::applyMaskPenaltyRule2($matrix)
+            + MaskUtil::applyMaskPenaltyRule3($matrix)
+            + MaskUtil::applyMaskPenaltyRule4($matrix)
+        );
+    }
+
+    /**
+     * Chooses the best mask pattern for a matrix.
+     *
+     * @param  BitArray             $bits
+     * @param  ErrorCorrectionLevel $ecLevel
+     * @param  Version              $version
+     * @param  ByteMatrix           $matrix
+     * @return integer
+     */
+    protected static function chooseMaskPattern(
+        BitArray $bits,
+        ErrorCorrectionLevel $ecLevel,
+        Version $version,
+        ByteMatrix $matrix
+    ) {
+        $minPenality     = PHP_INT_MAX;
+        $bestMaskPattern = -1;
+
+        for ($maskPattern = 0; $maskPattern < QrCode::NUM_MASK_PATTERNS; $maskPattern++) {
+            MatrixUtil::buildMatrix($bits, $ecLevel, $version, $maskPattern, $matrix);
+            $penalty = self::calculateMaskPenalty($matrix);
+
+            if ($penalty < $minPenality) {
+                $minPenality     = $penalty;
+                $bestMaskPattern = $maskPattern;
+            }
+        }
+
+        return $bestMaskPattern;
+    }
+
+    /**
+     * Chooses the best version for the input.
+     *
+     * @param  integer              $numInputBits
+     * @param  ErrorCorrectionLevel $ecLevel
+     * @return Version
+     * @throws Exception\WriterException
+     */
+    protected static function chooseVersion($numInputBits, ErrorCorrectionLevel $ecLevel)
+    {
+        for ($versionNum = 1; $versionNum <= 40; $versionNum++) {
+            $version  = Version::getVersionForNumber($versionNum);
+            $numBytes = $version->getTotalCodewords();
+
+            $ecBlocks   = $version->getEcBlocksForLevel($ecLevel);
+            $numEcBytes = $ecBlocks->getTotalEcCodewords();
+
+            $numDataBytes    = $numBytes - $numEcBytes;
+            $totalInputBytes = intval(($numInputBits + 8) / 8);
+
+            if ($numDataBytes >= $totalInputBytes) {
+                return $version;
+            }
+        }
+
+        throw new Exception\WriterException('Data too big');
+    }
+
+    /**
+     * Terminates the bits in a bit array.
+     *
+     * @param  integer  $numDataBytes
+     * @param  BitArray $bits
+     * @throws Exception\WriterException
+     */
+    protected static function terminateBits($numDataBytes, BitArray $bits)
+    {
+        $capacity = $numDataBytes << 3;
+
+        if ($bits->getSize() > $capacity) {
+            throw new Exception\WriterException('Data bits cannot fit in the QR code');
+        }
+
+        for ($i = 0; $i < 4 && $bits->getSize() < $capacity; $i++) {
+            $bits->appendBit(false);
+        }
+
+        $numBitsInLastByte = $bits->getSize() & 0x7;
+
+        if ($numBitsInLastByte > 0) {
+            for ($i = $numBitsInLastByte; $i < 8; $i++) {
+                $bits->appendBit(false);
+            }
+        }
+
+        $numPaddingBytes = $numDataBytes - $bits->getSizeInBytes();
+
+        for ($i = 0; $i < $numPaddingBytes; $i++) {
+            $bits->appendBits(($i & 0x1) === 0 ? 0xec : 0x11, 8);
+        }
+
+        if ($bits->getSize() !== $capacity) {
+            throw new Exception\WriterException('Bits size does not equal capacity');
+        }
+    }
+
+    /**
+     * Gets number of data- and EC bytes for a block ID.
+     *
+     * @param  integer $numTotalBytes
+     * @param  integer $numDataBytes
+     * @param  integer $numRsBlocks
+     * @param  integer $blockId
+     * @return array
+     * @throws Exception\WriterException
+     */
+    protected static function getNumDataBytesAndNumEcBytesForBlockId(
+        $numTotalBytes,
+        $numDataBytes,
+        $numRsBlocks,
+        $blockId
+    ) {
+        if ($blockId >= $numRsBlocks) {
+            throw new Exception\WriterException('Block ID too large');
+        }
+
+        $numRsBlocksInGroup2   = $numTotalBytes % $numRsBlocks;
+        $numRsBlocksInGroup1   = $numRsBlocks - $numRsBlocksInGroup2;
+        $numTotalBytesInGroup1 = intval($numTotalBytes / $numRsBlocks);
+        $numTotalBytesInGroup2 = $numTotalBytesInGroup1 + 1;
+        $numDataBytesInGroup1  = intval($numDataBytes / $numRsBlocks);
+        $numDataBytesInGroup2  = $numDataBytesInGroup1 + 1;
+        $numEcBytesInGroup1    = $numTotalBytesInGroup1 - $numDataBytesInGroup1;
+        $numEcBytesInGroup2    = $numTotalBytesInGroup2 - $numDataBytesInGroup2;
+
+        if ($numEcBytesInGroup1 !== $numEcBytesInGroup2) {
+            throw new Exception\WriterException('EC bytes mismatch');
+        }
+
+        if ($numRsBlocks !== $numRsBlocksInGroup1 + $numRsBlocksInGroup2) {
+            throw new Exception\WriterException('RS blocks mismatch');
+        }
+
+        if ($numTotalBytes !==
+            (($numDataBytesInGroup1 + $numEcBytesInGroup1) * $numRsBlocksInGroup1)
+            + (($numDataBytesInGroup2 + $numEcBytesInGroup2) * $numRsBlocksInGroup2)
+        ) {
+            throw new Exception\WriterException('Total bytes mismatch');
+        }
+
+        if ($blockId < $numRsBlocksInGroup1) {
+            return array($numDataBytesInGroup1, $numEcBytesInGroup1);
+        } else {
+            return array($numDataBytesInGroup2, $numEcBytesInGroup2);
+        }
+    }
+
+    /**
+     * Interleaves data with EC bytes.
+     *
+     * @param  BitArray $bits
+     * @param  integer  $numTotalBytes
+     * @param  integer  $numDataBytes
+     * @param  integer  $numRsBlocks
+     * @return BitArray
+     * @throws Exception\WriterException
+     */
+    protected static function interleaveWithEcBytes(BitArray $bits, $numTotalBytes, $numDataBytes, $numRsBlocks)
+    {
+        if ($bits->getSizeInBytes() !== $numDataBytes) {
+            throw new Exception\WriterException('Number of bits and data bytes does not match');
+        }
+
+        $dataBytesOffset = 0;
+        $maxNumDataBytes = 0;
+        $maxNumEcBytes   = 0;
+
+        $blocks = new SplFixedArray($numRsBlocks);
+
+        for ($i = 0; $i < $numRsBlocks; $i++) {
+            list($numDataBytesInBlock, $numEcBytesInBlock) = self::getNumDataBytesAndNumEcBytesForBlockId(
+                $numTotalBytes,
+                $numDataBytes,
+                $numRsBlocks,
+                $i
+            );
+
+            $size       = $numDataBytesInBlock;
+            $dataBytes  = $bits->toBytes(8 * $dataBytesOffset, $size);
+            $ecBytes    = self::generateEcBytes($dataBytes, $numEcBytesInBlock);
+            $blocks[$i] = new BlockPair($dataBytes, $ecBytes);
+
+            $maxNumDataBytes  = max($maxNumDataBytes, $size);
+            $maxNumEcBytes    = max($maxNumEcBytes, count($ecBytes));
+            $dataBytesOffset += $numDataBytesInBlock;
+        }
+
+        if ($numDataBytes !== $dataBytesOffset) {
+            throw new Exception\WriterException('Data bytes does not match offset');
+        }
+
+        $result = new BitArray();
+
+        for ($i = 0; $i < $maxNumDataBytes; $i++) {
+            foreach ($blocks as $block) {
+                $dataBytes = $block->getDataBytes();
+
+                if ($i < count($dataBytes)) {
+                    $result->appendBits($dataBytes[$i], 8);
+                }
+            }
+        }
+
+        for ($i = 0; $i < $maxNumEcBytes; $i++) {
+            foreach ($blocks as $block) {
+                $ecBytes = $block->getErrorCorrectionBytes();
+
+                if ($i < count($ecBytes)) {
+                    $result->appendBits($ecBytes[$i], 8);
+                }
+            }
+        }
+
+        if ($numTotalBytes !== $result->getSizeInBytes()) {
+            throw new Exception\WriterException('Interleaving error: ' . $numTotalBytes . ' and ' . $result->getSizeInBytes() . ' differ');
+        }
+
+        return $result;
+    }
+
+    /**
+     * Generates EC bytes for given data.
+     *
+     * @param  SplFixedArray $dataBytes
+     * @param  integer       $numEcBytesInBlock
+     * @return SplFixedArray
+     */
+    protected static function generateEcBytes(SplFixedArray $dataBytes, $numEcBytesInBlock)
+    {
+        $numDataBytes = count($dataBytes);
+        $toEncode     = new SplFixedArray($numDataBytes + $numEcBytesInBlock);
+
+        for ($i = 0; $i < $numDataBytes; $i++) {
+            $toEncode[$i] = $dataBytes[$i] & 0xff;
+        }
+
+        $ecBytes = new SplFixedArray($numEcBytesInBlock);
+        $codec   = self::getCodec($numDataBytes, $numEcBytesInBlock);
+        $codec->encode($toEncode, $ecBytes);
+
+        return $ecBytes;
+    }
+
+    /**
+     * Gets an RS codec and caches it.
+     *
+     * @param  integer $numDataBytes
+     * @param  integer $numEcBytesInBlock
+     * @return ReedSolomonCodec
+     */
+    protected static function getCodec($numDataBytes, $numEcBytesInBlock)
+    {
+        $cacheId = $numDataBytes . '-' . $numEcBytesInBlock;
+
+        if (!isset(self::$codecs[$cacheId])) {
+            self::$codecs[$cacheId] = new ReedSolomonCodec(
+                8,
+                0x11d,
+                0,
+                1,
+                $numEcBytesInBlock,
+                255 - $numDataBytes - $numEcBytesInBlock
+            );
+        }
+
+        return self::$codecs[$cacheId];
+    }
+
+    /**
+     * Appends mode information to a bit array.
+     *
+     * @param  Mode     $mode
+     * @param  BitArray $bits
+     * @return void
+     */
+    protected static function appendModeInfo(Mode $mode, BitArray $bits)
+    {
+        $bits->appendBits($mode->get(), 4);
+    }
+
+    /**
+     * Appends length information to a bit array.
+     *
+     * @param  integer  $numLetters
+     * @param  Version  $version
+     * @param  Mode     $mode
+     * @param  BitArray $bits
+     * @return void
+     * @throws Exception\WriterException
+     */
+    protected static function appendLengthInfo($numLetters, Version $version, Mode $mode, BitArray $bits)
+    {
+        $numBits = $mode->getCharacterCountBits($version);
+
+        if ($numLetters >= (1 << $numBits)) {
+            throw new Exception\WriterException($numLetters . ' is bigger than ' . ((1 << $numBits) - 1));
+        }
+
+        $bits->appendBits($numLetters, $numBits);
+    }
+
+    /**
+     * Appends bytes to a bit array in a specific mode.
+     *
+     * @param  stirng   $content
+     * @param  Mode     $mode
+     * @param  BitArray $bits
+     * @param  string   $encoding
+     * @return void
+     * @throws Exception\WriterException
+     */
+    protected static function appendBytes($content, Mode $mode, BitArray $bits, $encoding)
+    {
+        switch ($mode->get()) {
+            case Mode::NUMERIC:
+                self::appendNumericBytes($content, $bits);
+                break;
+
+            case Mode::ALPHANUMERIC:
+                self::appendAlphanumericBytes($content, $bits);
+                break;
+
+            case Mode::BYTE:
+                self::append8BitBytes($content, $bits, $encoding);
+                break;
+
+            case Mode::KANJI:
+                self::appendKanjiBytes($content, $bits);
+                break;
+
+            default:
+                throw new Exception\WriterException('Invalid mode: ' . $mode->get());
+        }
+    }
+
+    /**
+     * Appends numeric bytes to a bit array.
+     *
+     * @param  string   $content
+     * @param  BitArray $bits
+     * @return void
+     */
+    protected static function appendNumericBytes($content, BitArray $bits)
+    {
+        $length = strlen($content);
+        $i      = 0;
+
+        while ($i < $length) {
+            $num1 = (int) $content[$i];
+
+            if ($i + 2 < $length) {
+                // Encode three numeric letters in ten bits.
+                $num2 = (int) $content[$i + 1];
+                $num3 = (int) $content[$i + 2];
+                $bits->appendBits($num1 * 100 + $num2 * 10 + $num3, 10);
+                $i += 3;
+            } elseif ($i + 1 < $length) {
+                // Encode two numeric letters in seven bits.
+                $num2 = (int) $content[$i + 1];
+                $bits->appendBits($num1 * 10 + $num2, 7);
+                $i += 2;
+            } else {
+                // Encode one numeric letter in four bits.
+                $bits->appendBits($num1, 4);
+                $i++;
+            }
+        }
+    }
+
+    /**
+     * Appends alpha-numeric bytes to a bit array.
+     *
+     * @param  string   $content
+     * @param  BitArray $bits
+     * @return void
+     */
+    protected static function appendAlphanumericBytes($content, BitArray $bits)
+    {
+        $length = strlen($content);
+        $i      = 0;
+
+        while ($i < $length) {
+            if (-1 === ($code1 = self::getAlphanumericCode($content[$i]))) {
+                throw new Exception\WriterException('Invalid alphanumeric code');
+            }
+
+            if ($i + 1 < $length) {
+                if (-1 === ($code2 = self::getAlphanumericCode($content[$i + 1]))) {
+                    throw new Exception\WriterException('Invalid alphanumeric code');
+                }
+
+                // Encode two alphanumeric letters in 11 bits.
+                $bits->appendBits($code1 * 45 + $code2, 11);
+                $i += 2;
+            } else {
+                // Encode one alphanumeric letter in six bits.
+                $bits->appendBits($code1, 6);
+                $i++;
+            }
+        }
+    }
+
+    /**
+     * Appends regular 8-bit bytes to a bit array.
+     *
+     * @param  string   $content
+     * @param  BitArray $bits
+     * @return void
+     */
+    protected static function append8BitBytes($content, BitArray $bits, $encoding)
+    {
+        if (false === ($bytes = @iconv('utf-8', $encoding, $content))) {
+            throw new Exception\WriterException('Could not encode content to ' . $encoding);
+        }
+
+        $length = strlen($bytes);
+
+        for ($i = 0; $i < $length; $i++) {
+            $bits->appendBits(ord($bytes[$i]), 8);
+        }
+    }
+
+    /**
+     * Appends KANJI bytes to a bit array.
+     *
+     * @param  string   $content
+     * @param  BitArray $bits
+     * @return void
+     */
+    protected static function appendKanjiBytes($content, BitArray $bits)
+    {
+        if (strlen($content) % 2 > 0) {
+            // We just do a simple length check here. The for loop will check
+            // individual characters.
+            throw new Exception\WriterException('Content does not seem to be encoded in SHIFT-JIS');
+        }
+
+        $length = strlen($content);
+
+        for ($i = 0; $i < $length; $i += 2) {
+            $byte1 = ord($content[$i]) & 0xff;
+            $byte2 = ord($content[$i + 1]) & 0xff;
+            $code  = ($byte1 << 8) | $byte2;
+
+            if ($code >= 0x8140 && $code <= 0x9ffc) {
+                $subtracted = $code - 0x8140;
+            } elseif ($code >= 0xe040 && $code <= 0xebbf) {
+                $subtracted = $code - 0xc140;
+            } else {
+                throw new Exception\WriterException('Invalid byte sequence');
+            }
+
+            $encoded = (($subtracted >> 8) * 0xc0) + ($subtracted & 0xff);
+
+            $bits->appendBits($encoded, 13);
+        }
+    }
+
+    /**
+     * Appends ECI information to a bit array.
+     *
+     * @param  CharacterSetEci $eci
+     * @param  BitArray        $bits
+     * @return void
+     */
+    protected static function appendEci(CharacterSetEci $eci, BitArray $bits)
+    {
+        $mode = new Mode(Mode::ECI);
+        $bits->appendBits($mode->get(), 4);
+        $bits->appendBits($eci->get(), 8);
+    }
+}

+ 291 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MaskUtil.php

@@ -0,0 +1,291 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\BitUtils;
+
+/**
+ * Mask utility.
+ */
+class MaskUtil
+{
+    /**#@+
+     * Penalty weights from section 6.8.2.1
+     */
+    const N1 = 3;
+    const N2 = 3;
+    const N3 = 40;
+    const N4 = 10;
+    /**#@-*/
+
+    /**
+     * Applies mask penalty rule 1 and returns the penalty.
+     *
+     * Finds repetitive cells with the same color and gives penalty to them.
+     * Example: 00000 or 11111.
+     *
+     * @param  ByteMatrix $matrix
+     * @return integer
+     */
+    public static function applyMaskPenaltyRule1(ByteMatrix $matrix)
+    {
+        return (
+            self::applyMaskPenaltyRule1Internal($matrix, true)
+            + self::applyMaskPenaltyRule1Internal($matrix, false)
+        );
+    }
+
+    /**
+     * Applies mask penalty rule 2 and returns the penalty.
+     *
+     * Finds 2x2 blocks with the same color and gives penalty to them. This is
+     * actually equivalent to the spec's rule, which is to find MxN blocks and
+     * give a penalty proportional to (M-1)x(N-1), because this is the number of
+     * 2x2 blocks inside such a block.
+     *
+     * @param  ByteMatrix $matrix
+     * @return integer
+     */
+    public static function applyMaskPenaltyRule2(ByteMatrix $matrix)
+    {
+        $penalty = 0;
+        $array   = $matrix->getArray();
+        $width   = $matrix->getWidth();
+        $height  = $matrix->getHeight();
+
+        for ($y = 0; $y < $height - 1; $y++) {
+            for ($x = 0; $x < $width - 1; $x++) {
+                $value = $array[$y][$x];
+
+                if ($value === $array[$y][$x + 1] && $value === $array[$y + 1][$x] && $value === $array[$y + 1][$x + 1]) {
+                    $penalty++;
+                }
+            }
+        }
+
+        return self::N2 * $penalty;
+    }
+
+    /**
+     * Applies mask penalty rule 3 and returns the penalty.
+     *
+     * Finds consecutive cells of 00001011101 or 10111010000, and gives penalty
+     * to them. If we find patterns like 000010111010000, we give penalties
+     * twice (i.e. 40 * 2).
+     *
+     * @param  ByteMatrix $matrix
+     * @return integer
+     */
+    public static function applyMaskPenaltyRule3(ByteMatrix $matrix)
+    {
+        $penalty = 0;
+        $array   = $matrix->getArray();
+        $width   = $matrix->getWidth();
+        $height  = $matrix->getHeight();
+
+        for ($y = 0; $y < $height; $y++) {
+            for ($x = 0; $x < $width; $x++) {
+                if (
+                    $x + 6 < $width
+                    && $array[$y][$x] === 1
+                    && $array[$y][$x + 1] === 0
+                    && $array[$y][$x + 2] === 1
+                    && $array[$y][$x + 3] === 1
+                    && $array[$y][$x + 4] === 1
+                    && $array[$y][$x + 5] === 0
+                    && $array[$y][$x + 6] === 1
+                    && (
+                        (
+                            $x + 10 < $width
+                            && $array[$y][$x + 7] === 0
+                            && $array[$y][$x + 8] === 0
+                            && $array[$y][$x + 9] === 0
+                            && $array[$y][$x + 10] === 0
+                        )
+                        || (
+                            $x - 4 >= 0
+                            && $array[$y][$x - 1] === 0
+                            && $array[$y][$x - 2] === 0
+                            && $array[$y][$x - 3] === 0
+                            && $array[$y][$x - 4] === 0
+                        )
+                    )
+                ) {
+                    $penalty += self::N3;
+                }
+
+                if (
+                    $y + 6 < $height
+                    && $array[$y][$x] === 1
+                    && $array[$y + 1][$x] === 0
+                    && $array[$y + 2][$x] === 1
+                    && $array[$y + 3][$x] === 1
+                    && $array[$y + 4][$x] === 1
+                    && $array[$y + 5][$x] === 0
+                    && $array[$y + 6][$x] === 1
+                    && (
+                        (
+                            $y + 10 < $height
+                            && $array[$y + 7][$x] === 0
+                            && $array[$y + 8][$x] === 0
+                            && $array[$y + 9][$x] === 0
+                            && $array[$y + 10][$x] === 0
+                        )
+                        || (
+                            $y - 4 >= 0
+                            && $array[$y - 1][$x] === 0
+                            && $array[$y - 2][$x] === 0
+                            && $array[$y - 3][$x] === 0
+                            && $array[$y - 4][$x] === 0
+                        )
+                    )
+                ) {
+                    $penalty += self::N3;
+                }
+            }
+        }
+
+        return $penalty;
+    }
+
+    /**
+     * Applies mask penalty rule 4 and returns the penalty.
+     *
+     * Calculates the ratio of dark cells and gives penalty if the ratio is far
+     * from 50%. It gives 10 penalty for 5% distance.
+     *
+     * @param  ByteMatrix $matrix
+     * @return integer
+     */
+    public static function applyMaskPenaltyRule4(ByteMatrix $matrix)
+    {
+        $numDarkCells = 0;
+
+        $array  = $matrix->getArray();
+        $width  = $matrix->getWidth();
+        $height = $matrix->getHeight();
+
+        for ($y = 0; $y < $height; $y++) {
+            $arrayY = $array[$y];
+
+            for ($x = 0; $x < $width; $x++) {
+                if ($arrayY[$x] === 1) {
+                    $numDarkCells++;
+                }
+            }
+        }
+
+        $numTotalCells         = $height * $width;
+        $darkRatio             = $numDarkCells / $numTotalCells;
+        $fixedPercentVariances = (int) (abs($darkRatio - 0.5) * 20);
+
+        return $fixedPercentVariances * self::N4;
+    }
+
+    /**
+     * Returns the mask bit for "getMaskPattern" at "x" and "y".
+     *
+     * See 8.8 of JISX0510:2004 for mask pattern conditions.
+     *
+     * @param  integer $maskPattern
+     * @param  integer $x
+     * @param  integer $y
+     * @return integer
+     * @throws Exception\InvalidArgumentException
+     */
+    public static function getDataMaskBit($maskPattern, $x, $y)
+    {
+        switch ($maskPattern) {
+            case 0:
+                $intermediate = ($y + $x) & 0x1;
+                break;
+
+            case 1:
+                $intermediate = $y & 0x1;
+                break;
+
+            case 2:
+                $intermediate = $x % 3;
+                break;
+
+            case 3:
+                $intermediate = ($y + $x) % 3;
+                break;
+
+            case 4:
+                $intermediate = (BitUtils::unsignedRightShift($y, 1) + ($x / 3)) & 0x1;
+                break;
+
+            case 5:
+                $temp         = $y * $x;
+                $intermediate = ($temp & 0x1) + ($temp % 3);
+                break;
+
+            case 6:
+                $temp         = $y * $x;
+                $intermediate = (($temp & 0x1) + ($temp % 3)) & 0x1;
+                break;
+
+            case 7:
+                $temp         = $y * $x;
+                $intermediate = (($temp % 3) + (($y + $x) & 0x1)) & 0x1;
+                break;
+
+            default:
+                throw new Exception\InvalidArgumentException('Invalid mask pattern: ' . $maskPattern);
+        }
+
+        return $intermediate === 0;
+    }
+
+    /**
+     * Helper function for applyMaskPenaltyRule1.
+     *
+     * We need this for doing this calculation in both vertical and horizontal
+     * orders respectively.
+     *
+     * @param  ByteMatrix $matrix
+     * @param  boolean    $isHorizontal
+     * @return integer
+     */
+    protected static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, $isHorizontal)
+    {
+        $penalty = 0;
+        $iLimit  = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth();
+        $jLimit  = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight();
+        $array   = $matrix->getArray();
+
+        for ($i = 0; $i < $iLimit; $i++) {
+            $numSameBitCells = 0;
+            $prevBit         = -1;
+
+            for ($j = 0; $j < $jLimit; $j++) {
+                $bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i];
+
+                if ($bit === $prevBit) {
+                    $numSameBitCells++;
+                } else {
+                    if ($numSameBitCells >= 5) {
+                        $penalty += self::N1 + ($numSameBitCells - 5);
+                    }
+
+                    $numSameBitCells = 1;
+                    $prevBit         = $bit;
+                }
+            }
+
+            if ($numSameBitCells >= 5) {
+                $penalty += self::N1 + ($numSameBitCells - 5);
+            }
+        }
+
+        return $penalty;
+    }
+}

+ 580 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/MatrixUtil.php

@@ -0,0 +1,580 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\BitArray;
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Common\Version;
+use BaconQrCode\Exception;
+
+/**
+ * Matrix utility.
+ */
+class MatrixUtil
+{
+    /**
+     * Position detection pattern.
+     *
+     * @var array
+     */
+    protected static $positionDetectionPattern = array(
+        array(1, 1, 1, 1, 1, 1, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 0, 1, 1, 1, 0, 1),
+        array(1, 0, 1, 1, 1, 0, 1),
+        array(1, 0, 1, 1, 1, 0, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 1, 1, 1, 1, 1, 1),
+    );
+
+    /**
+     * Position adjustment pattern.
+     *
+     * @var array
+     */
+    protected static $positionAdjustmentPattern = array(
+        array(1, 1, 1, 1, 1),
+        array(1, 0, 0, 0, 1),
+        array(1, 0, 1, 0, 1),
+        array(1, 0, 0, 0, 1),
+        array(1, 1, 1, 1, 1),
+    );
+
+    /**
+     * Coordinates for position adjustment patterns for each version.
+     *
+     * @var array
+     */
+    protected static $positionAdjustmentPatternCoordinateTable = array(
+        array(null, null, null, null, null, null, null), // Version 1
+        array(   6,   18, null, null, null, null, null), // Version 2
+        array(   6,   22, null, null, null, null, null), // Version 3
+        array(   6,   26, null, null, null, null, null), // Version 4
+        array(   6,   30, null, null, null, null, null), // Version 5
+        array(   6,   34, null, null, null, null, null), // Version 6
+        array(   6,   22,   38, null, null, null, null), // Version 7
+        array(   6,   24,   42, null, null, null, null), // Version 8
+        array(   6,   26,   46, null, null, null, null), // Version 9
+        array(   6,   28,   50, null, null, null, null), // Version 10
+        array(   6,   30,   54, null, null, null, null), // Version 11
+        array(   6,   32,   58, null, null, null, null), // Version 12
+        array(   6,   34,   62, null, null, null, null), // Version 13
+        array(   6,   26,   46,   66, null, null, null), // Version 14
+        array(   6,   26,   48,   70, null, null, null), // Version 15
+        array(   6,   26,   50,   74, null, null, null), // Version 16
+        array(   6,   30,   54,   78, null, null, null), // Version 17
+        array(   6,   30,   56,   82, null, null, null), // Version 18
+        array(   6,   30,   58,   86, null, null, null), // Version 19
+        array(   6,   34,   62,   90, null, null, null), // Version 20
+        array(   6,   28,   50,   72,   94, null, null), // Version 21
+        array(   6,   26,   50,   74,   98, null, null), // Version 22
+        array(   6,   30,   54,   78,  102, null, null), // Version 23
+        array(   6,   28,   54,   80,  106, null, null), // Version 24
+        array(   6,   32,   58,   84,  110, null, null), // Version 25
+        array(   6,   30,   58,   86,  114, null, null), // Version 26
+        array(   6,   34,   62,   90,  118, null, null), // Version 27
+        array(   6,   26,   50,   74,   98,  122, null), // Version 28
+        array(   6,   30,   54,   78,  102,  126, null), // Version 29
+        array(   6,   26,   52,   78,  104,  130, null), // Version 30
+        array(   6,   30,   56,   82,  108,  134, null), // Version 31
+        array(   6,   34,   60,   86,  112,  138, null), // Version 32
+        array(   6,   30,   58,   86,  114,  142, null), // Version 33
+        array(   6,   34,   62,   90,  118,  146, null), // Version 34
+        array(   6,   30,   54,   78,  102,  126,  150), // Version 35
+        array(   6,   24,   50,   76,  102,  128,  154), // Version 36
+        array(   6,   28,   54,   80,  106,  132,  158), // Version 37
+        array(   6,   32,   58,   84,  110,  136,  162), // Version 38
+        array(   6,   26,   54,   82,  110,  138,  166), // Version 39
+        array(   6,   30,   58,   86,  114,  142,  170), // Version 40
+    );
+
+    /**
+     * Type information coordinates.
+     *
+     * @var array
+     */
+    protected static $typeInfoCoordinates = array(
+        array(8, 0),
+        array(8, 1),
+        array(8, 2),
+        array(8, 3),
+        array(8, 4),
+        array(8, 5),
+        array(8, 7),
+        array(8, 8),
+        array(7, 8),
+        array(5, 8),
+        array(4, 8),
+        array(3, 8),
+        array(2, 8),
+        array(1, 8),
+        array(0, 8),
+    );
+
+    /**
+     * Version information polynomial.
+     *
+     * @var integer
+     */
+    protected static $versionInfoPoly = 0x1f25;
+
+    /**
+     * Type information polynomial.
+     *
+     * @var integer
+     */
+    protected static $typeInfoPoly = 0x537;
+
+    /**
+     * Type information mask pattern.
+     *
+     * @var integer
+     */
+    protected static $typeInfoMaskPattern = 0x5412;
+
+    /**
+     * Clears a given matrix.
+     *
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    public static function clearMatrix(ByteMatrix $matrix)
+    {
+        $matrix->clear(-1);
+    }
+
+    /**
+     * Builds a complete matrix.
+     *
+     * @param  BitArray             $dataBits
+     * @param  ErrorCorrectionLevel $level
+     * @param  Version              $version
+     * @param  integer              $maskPattern
+     * @param  ByteMatrix           $matrix
+     * @return void
+     */
+    public static function buildMatrix(
+        BitArray $dataBits,
+        ErrorCorrectionLevel $level,
+        Version $version,
+        $maskPattern,
+        ByteMatrix $matrix
+    ) {
+        self::clearMatrix($matrix);
+        self::embedBasicPatterns($version, $matrix);
+        self::embedTypeInfo($level, $maskPattern, $matrix);
+        self::maybeEmbedVersionInfo($version, $matrix);
+        self::embedDataBits($dataBits, $maskPattern, $matrix);
+    }
+
+    /**
+     * Embeds type information into a matrix.
+     *
+     * @param  ErrorCorrectionLevel $level
+     * @param  integer              $maskPattern
+     * @param  ByteMatrix           $matrix
+     * @return void
+     */
+    protected static function embedTypeInfo(ErrorCorrectionLevel $level, $maskPattern, ByteMatrix $matrix)
+    {
+        $typeInfoBits = new BitArray();
+        self::makeTypeInfoBits($level, $maskPattern, $typeInfoBits);
+
+        $typeInfoBitsSize = $typeInfoBits->getSize();
+
+        for ($i = 0; $i < $typeInfoBitsSize; $i++) {
+            $bit = $typeInfoBits->get($typeInfoBitsSize - 1 - $i);
+
+            $x1 = self::$typeInfoCoordinates[$i][0];
+            $y1 = self::$typeInfoCoordinates[$i][1];
+
+            $matrix->set($x1, $y1, $bit);
+
+            if ($i < 8) {
+                $x2 = $matrix->getWidth() - $i - 1;
+                $y2 = 8;
+            } else {
+                $x2 = 8;
+                $y2 = $matrix->getHeight() - 7 + ($i - 8);
+            }
+
+            $matrix->set($x2, $y2, $bit);
+        }
+    }
+
+    /**
+     * Generates type information bits and appends them to a bit array.
+     *
+     * @param  ErrorCorrectionLevel $level
+     * @param  integer $maskPattern
+     * @param  BitArray $bits
+     * @return void
+     * @throws Exception\RuntimeException
+     */
+    protected static function makeTypeInfoBits(ErrorCorrectionLevel $level, $maskPattern, BitArray $bits)
+    {
+        $typeInfo = ($level->get() << 3) | $maskPattern;
+        $bits->appendBits($typeInfo, 5);
+
+        $bchCode = self::calculateBchCode($typeInfo, self::$typeInfoPoly);
+        $bits->appendBits($bchCode, 10);
+
+        $maskBits = new BitArray();
+        $maskBits->appendBits(self::$typeInfoMaskPattern, 15);
+        $bits->xorBits($maskBits);
+
+        if ($bits->getSize() !== 15) {
+            throw new Exception\RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
+        }
+    }
+
+    /**
+     * Embeds version information if required.
+     *
+     * @param  Version    $version
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function maybeEmbedVersionInfo(Version $version, ByteMatrix $matrix)
+    {
+        if ($version->getVersionNumber() < 7) {
+            return;
+        }
+
+        $versionInfoBits = new BitArray();
+        self::makeVersionInfoBits($version, $versionInfoBits);
+
+        $bitIndex = 6 * 3 - 1;
+
+        for ($i = 0; $i < 6; $i++) {
+            for ($j = 0; $j < 3; $j++) {
+                $bit = $versionInfoBits->get($bitIndex);
+                $bitIndex--;
+
+                $matrix->set($i, $matrix->getHeight() - 11 + $j, $bit);
+                $matrix->set($matrix->getHeight() - 11 + $j, $i, $bit);
+            }
+        }
+    }
+
+    /**
+     * Generates version information bits and appends them to a bit array.
+     *
+     * @param  Version  $version
+     * @param  BitArray $bits
+     * @return void
+     * @throws Exception\RuntimeException
+     */
+    protected static function makeVersionInfoBits(Version $version, BitArray $bits)
+    {
+        $bits->appendBits($version->getVersionNumber(), 6);
+
+        $bchCode = self::calculateBchCode($version->getVersionNumber(), self::$versionInfoPoly);
+        $bits->appendBits($bchCode, 12);
+
+        if ($bits->getSize() !== 18) {
+            throw new Exception\RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
+        }
+    }
+
+    /**
+     * Calculates the BHC code for a value and a polynomial.
+     *
+     * @param  integer $value
+     * @param  integer $poly
+     * @return integer
+     */
+    protected static function calculateBchCode($value, $poly)
+    {
+        $msbSetInPoly   = self::findMsbSet($poly);
+        $value        <<= $msbSetInPoly - 1;
+
+        while (self::findMsbSet($value) >= $msbSetInPoly) {
+            $value ^= $poly << (self::findMsbSet($value) - $msbSetInPoly);
+        }
+
+        return $value;
+    }
+
+    /**
+     * Finds and MSB set.
+     *
+     * @param  integer $value
+     * @return integer
+     */
+    protected static function findMsbSet($value)
+    {
+        $numDigits = 0;
+
+        while ($value !== 0) {
+            $value >>= 1;
+            $numDigits++;
+        }
+
+        return $numDigits;
+    }
+
+    /**
+     * Embeds basic patterns into a matrix.
+     *
+     * @param  Version    $version
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function embedBasicPatterns(Version $version, ByteMatrix $matrix)
+    {
+        self::embedPositionDetectionPatternsAndSeparators($matrix);
+        self::embedDarkDotAtLeftBottomCorner($matrix);
+        self::maybeEmbedPositionAdjustmentPatterns($version, $matrix);
+        self::embedTimingPatterns($matrix);
+    }
+
+    /**
+     * Embeds position detection patterns and separators into a byte matrix.
+     *
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function embedPositionDetectionPatternsAndSeparators(ByteMatrix $matrix)
+    {
+        $pdpWidth = count(self::$positionDetectionPattern[0]);
+
+        self::embedPositionDetectionPattern(0, 0, $matrix);
+        self::embedPositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix);
+        self::embedPositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix);
+
+        $hspWidth = 8;
+
+        self::embedHorizontalSeparationPattern(0, $hspWidth - 1, $matrix);
+        self::embedHorizontalSeparationPattern($matrix->getWidth() - $hspWidth, $hspWidth - 1, $matrix);
+        self::embedHorizontalSeparationPattern(0, $matrix->getWidth() - $hspWidth, $matrix);
+
+        $vspSize = 7;
+
+        self::embedVerticalSeparationPattern($vspSize, 0, $matrix);
+        self::embedVerticalSeparationPattern($matrix->getHeight() - $vspSize - 1, 0, $matrix);
+        self::embedVerticalSeparationPattern($vspSize, $matrix->getHeight() - $vspSize, $matrix);
+    }
+
+    /**
+     * Embeds a single position detection pattern into a byte matrix.
+     *
+     * @param  integer    $xStart
+     * @param  integer    $yStart
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function embedPositionDetectionPattern($xStart, $yStart, ByteMatrix $matrix)
+    {
+        for ($y = 0; $y < 7; $y++) {
+            for ($x = 0; $x < 7; $x++) {
+                $matrix->set($xStart + $x, $yStart + $y, self::$positionDetectionPattern[$y][$x]);
+            }
+        }
+    }
+
+    /**
+     * Embeds a single horizontal separation pattern.
+     *
+     * @param  integer    $xStart
+     * @param  integer    $yStart
+     * @param  ByteMatrix $matrix
+     * @return void
+     * @throws Exception\RuntimeException
+     */
+    protected static function embedHorizontalSeparationPattern($xStart, $yStart, ByteMatrix $matrix)
+    {
+        for ($x = 0; $x < 8; $x++) {
+            if ($matrix->get($xStart + $x, $yStart) !== -1) {
+                throw new Exception\RuntimeException('Byte already set');
+            }
+
+            $matrix->set($xStart + $x, $yStart, 0);
+        }
+    }
+
+    /**
+     * Embeds a single vertical separation pattern.
+     *
+     * @param  integer    $xStart
+     * @param  integer    $yStart
+     * @param  ByteMatrix $matrix
+     * @return void
+     * @throws Exception\RuntimeException
+     */
+    protected static function embedVerticalSeparationPattern($xStart, $yStart, ByteMatrix $matrix)
+    {
+        for ($y = 0; $y < 7; $y++) {
+            if ($matrix->get($xStart, $yStart + $y) !== -1) {
+                throw new Exception\RuntimeException('Byte already set');
+            }
+
+            $matrix->set($xStart, $yStart + $y, 0);
+        }
+    }
+
+    /**
+     * Embeds a dot at the left bottom corner.
+     *
+     * @param  ByteMatrix $matrix
+     * @return void
+     * @throws Exception\RuntimeException
+     */
+    protected static function embedDarkDotAtLeftBottomCorner(ByteMatrix $matrix)
+    {
+        if ($matrix->get(8, $matrix->getHeight() - 8) === 0) {
+            throw new Exception\RuntimeException('Byte already set to 0');
+        }
+
+        $matrix->set(8, $matrix->getHeight() - 8, 1);
+    }
+
+    /**
+     * Embeds position adjustment patterns if required.
+     *
+     * @param  Version    $version
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function maybeEmbedPositionAdjustmentPatterns(Version $version, ByteMatrix $matrix)
+    {
+        if ($version->getVersionNumber() < 2) {
+            return;
+        }
+
+        $index = $version->getVersionNumber() - 1;
+
+        $coordinates    = self::$positionAdjustmentPatternCoordinateTable[$index];
+        $numCoordinates = count($coordinates);
+
+        for ($i = 0; $i < $numCoordinates; $i++) {
+            for ($j = 0; $j < $numCoordinates; $j++) {
+                $y = $coordinates[$i];
+                $x = $coordinates[$j];
+
+                if ($x === null || $y === null) {
+                    continue;
+                }
+
+                if ($matrix->get($x, $y) === -1) {
+                    self::embedPositionAdjustmentPattern($x - 2, $y - 2, $matrix);
+                }
+            }
+        }
+    }
+
+    /**
+     * Embeds a single position adjustment pattern.
+     *
+     * @param  integer    $xStart
+     * @param  intger     $yStart
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function embedPositionAdjustmentPattern($xStart, $yStart, ByteMatrix $matrix)
+    {
+        for ($y = 0; $y < 5; $y++) {
+            for ($x = 0; $x < 5; $x++) {
+                $matrix->set($xStart + $x, $yStart + $y, self::$positionAdjustmentPattern[$y][$x]);
+            }
+        }
+    }
+
+    /**
+     * Embeds timing patterns into a matrix.
+     *
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    protected static function embedTimingPatterns(ByteMatrix $matrix)
+    {
+        $matrixWidth = $matrix->getWidth();
+
+        for ($i = 8; $i < $matrixWidth - 8; $i++) {
+            $bit = ($i + 1) % 2;
+
+            if ($matrix->get($i, 6) === -1) {
+                $matrix->set($i, 6, $bit);
+            }
+
+            if ($matrix->get(6, $i) === -1) {
+                $matrix->set(6, $i, $bit);
+            }
+        }
+    }
+
+    /**
+     * Embeds "dataBits" using "getMaskPattern".
+     *
+     *  For debugging purposes, it skips masking process if "getMaskPattern" is
+     * -1. See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
+     *
+     * @param  BitArray   $dataBits
+     * @param  integer    $maskPattern
+     * @param  ByteMatrix $matrix
+     * @return void
+     * @throws Exception\WriterException
+     */
+    protected static function embedDataBits(BitArray $dataBits, $maskPattern, ByteMatrix $matrix)
+    {
+        $bitIndex  = 0;
+        $direction = -1;
+
+        // Start from the right bottom cell.
+        $x = $matrix->getWidth() - 1;
+        $y = $matrix->getHeight() - 1;
+
+        while ($x > 0) {
+            // Skip vertical timing pattern.
+            if ($x === 6) {
+                $x--;
+            }
+
+            while ($y >= 0 && $y < $matrix->getHeight()) {
+                for ($i = 0; $i < 2; $i++) {
+                    $xx = $x - $i;
+
+                    // Skip the cell if it's not empty.
+                    if ($matrix->get($xx, $y) !== -1) {
+                        continue;
+                    }
+
+                    if ($bitIndex < $dataBits->getSize()) {
+                        $bit = $dataBits->get($bitIndex);
+                        $bitIndex++;
+                    } else {
+                        // Padding bit. If there is no bit left, we'll fill the
+                        // left cells with 0, as described in 8.4.9 of
+                        // JISX0510:2004 (p. 24).
+                        $bit = false;
+                    }
+
+                    // Skip masking if maskPattern is -1.
+                    if ($maskPattern !== -1 && MaskUtil::getDataMaskBit($maskPattern, $xx, $y)) {
+                        $bit = !$bit;
+                    }
+
+                    $matrix->set($xx, $y, $bit);
+                }
+
+                $y += $direction;
+            }
+
+            $direction  = -$direction;
+            $y         += $direction;
+            $x         -= 2;
+        }
+
+        // All bits should be consumed
+        if ($bitIndex !== $dataBits->getSize()) {
+            throw new Exception\WriterException('Not all bits consumed (' . $bitIndex . ' out of ' . $dataBits->getSize() .')');
+        }
+    }
+}

+ 201 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Encoder/QrCode.php

@@ -0,0 +1,201 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Common\Mode;
+use BaconQrCode\Common\Version;
+
+/**
+ * QR code.
+ */
+class QrCode
+{
+    /**
+     * Number of possible mask patterns.
+     */
+    const NUM_MASK_PATTERNS = 8;
+
+    /**
+     * Mode of the QR code.
+     *
+     * @var Mode
+     */
+    protected $mode;
+
+    /**
+     * EC level of the QR code.
+     *
+     * @var ErrorCorrectionLevel
+     */
+    protected $errorCorrectionLevel;
+
+    /**
+     * Version of the QR code.
+     *
+     * @var Version
+     */
+    protected $version;
+
+    /**
+     * Mask pattern of the QR code.
+     *
+     * @var integer
+     */
+    protected $maskPattern = -1;
+
+    /**
+     * Matrix of the QR code.
+     *
+     * @var ByteMatrix
+     */
+    protected $matrix;
+
+    /**
+     * Gets the mode.
+     *
+     * @return Mode
+     */
+    public function getMode()
+    {
+        return $this->mode;
+    }
+
+    /**
+     * Sets the mode.
+     *
+     * @param  Mode $mode
+     * @return void
+     */
+    public function setMode(Mode $mode)
+    {
+        $this->mode = $mode;
+    }
+
+    /**
+     * Gets the EC level.
+     *
+     * @return ErrorCorrectionLevel
+     */
+    public function getErrorCorrectionLevel()
+    {
+        return $this->errorCorrectionLevel;
+    }
+
+    /**
+     * Sets the EC level.
+     *
+     * @param  ErrorCorrectionLevel $errorCorrectionLevel
+     * @return void
+     */
+    public function setErrorCorrectionLevel(ErrorCorrectionLevel $errorCorrectionLevel)
+    {
+        $this->errorCorrectionLevel = $errorCorrectionLevel;
+    }
+
+    /**
+     * Gets the version.
+     *
+     * @return Version
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
+    /**
+     * Sets the version.
+     *
+     * @param  Version $version
+     * @return void
+     */
+    public function setVersion(Version $version)
+    {
+        $this->version = $version;
+    }
+
+    /**
+     * Gets the mask pattern.
+     *
+     * @return integer
+     */
+    public function getMaskPattern()
+    {
+        return $this->maskPattern;
+    }
+
+    /**
+     * Sets the mask pattern.
+     *
+     * @param  integer $maskPattern
+     * @return void
+     */
+    public function setMaskPattern($maskPattern)
+    {
+        $this->maskPattern = $maskPattern;
+    }
+
+    /**
+     * Gets the matrix.
+     *
+     * @return ByteMatrix
+     */
+    public function getMatrix()
+    {
+        return $this->matrix;
+    }
+
+    /**
+     * Sets the matrix.
+     *
+     * @param  ByteMatrix $matrix
+     * @return void
+     */
+    public function setMatrix(ByteMatrix $matrix)
+    {
+        $this->matrix = $matrix;
+    }
+
+    /**
+     * Validates whether a mask pattern is valid.
+     *
+     * @param  integer $maskPattern
+     * @return boolean
+     */
+    public static function isValidMaskPattern($maskPattern)
+    {
+        return $maskPattern > 0 && $maskPattern < self::NUM_MASK_PATTERNS;
+    }
+
+    /**
+     * Returns a string representation of the QR code.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        $result = "<<\n"
+                . " mode: " . $this->mode . "\n"
+                . " ecLevel: " . $this->errorCorrectionLevel . "\n"
+                . " version: " . $this->version . "\n"
+                . " maskPattern: " . $this->maskPattern . "\n";
+
+        if ($this->matrix === null) {
+            $result .= " matrix: null\n";
+        } else {
+            $result .= " matrix:\n";
+            $result .= $this->matrix;
+        }
+
+        $result .= ">>\n";
+
+        return $result;
+    }
+}

+ 14 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/ExceptionInterface.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Exception;
+
+interface ExceptionInterface
+{
+}

+ 14 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/InvalidArgumentException.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Exception;
+
+class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
+{
+}

+ 14 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/OutOfBoundsException.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Exception;
+
+class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
+{
+}

+ 14 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/RuntimeException.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Exception;
+
+class RuntimeException extends \RuntimeException implements ExceptionInterface
+{
+}

+ 14 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/UnexpectedValueException.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Exception;
+
+class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
+{
+}

+ 14 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Exception/WriterException.php

@@ -0,0 +1,14 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Exception;
+
+class WriterException extends \RuntimeException implements ExceptionInterface
+{
+}

+ 160 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Cmyk.php

@@ -0,0 +1,160 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Color;
+
+use BaconQrCode\Exception;
+
+/**
+ * CMYK color.
+ */
+class Cmyk implements ColorInterface
+{
+    /**
+     * Cyan value.
+     *
+     * @var integer
+     */
+    protected $cyan;
+
+    /**
+     * Magenta value.
+     *
+     * @var integer
+     */
+    protected $magenta;
+
+    /**
+     * Yellow value.
+     *
+     * @var integer
+     */
+    protected $yellow;
+
+    /**
+     * Black value.
+     *
+     * @var integer
+     */
+    protected $black;
+
+    /**
+     * Creates a new CMYK color.
+     *
+     * @param integer $cyan
+     * @param integer $magenta
+     * @param integer $yellow
+     * @param integer $black
+     */
+    public function __construct($cyan, $magenta, $yellow, $black)
+    {
+        if ($cyan < 0 || $cyan > 100) {
+            throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100');
+        }
+
+        if ($magenta < 0 || $magenta > 100) {
+            throw new Exception\InvalidArgumentException('Magenta must be between 0 and 100');
+        }
+
+        if ($yellow < 0 || $yellow > 100) {
+            throw new Exception\InvalidArgumentException('Yellow must be between 0 and 100');
+        }
+
+        if ($black < 0 || $black > 100) {
+            throw new Exception\InvalidArgumentException('Black must be between 0 and 100');
+        }
+
+        $this->cyan    = (int) $cyan;
+        $this->magenta = (int) $magenta;
+        $this->yellow  = (int) $yellow;
+        $this->black   = (int) $black;
+    }
+
+    /**
+     * Returns the cyan value.
+     *
+     * @return integer
+     */
+    public function getCyan()
+    {
+        return $this->cyan;
+    }
+
+    /**
+     * Returns the magenta value.
+     *
+     * @return integer
+     */
+    public function getMagenta()
+    {
+        return $this->magenta;
+    }
+
+    /**
+     * Returns the yellow value.
+     *
+     * @return integer
+     */
+    public function getYellow()
+    {
+        return $this->yellow;
+    }
+
+    /**
+     * Returns the black value.
+     *
+     * @return integer
+     */
+    public function getBlack()
+    {
+        return $this->black;
+    }
+
+    /**
+     * toRgb(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toRgb()
+     * @return Rgb
+     */
+    public function toRgb()
+    {
+        $k = $this->black / 100;
+        $c = (-$k * $this->cyan + $k * 100 + $this->cyan) / 100;
+        $m = (-$k * $this->magenta + $k * 100 + $this->magenta) / 100;
+        $y = (-$k * $this->yellow + $k * 100 + $this->yellow) / 100;
+
+        return new Rgb(
+            -$c * 255 + 255,
+            -$m * 255 + 255,
+            -$y * 255 + 255
+        );
+    }
+
+    /**
+     * toCmyk(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toCmyk()
+     * @return Cmyk
+     */
+    public function toCmyk()
+    {
+        return $this;
+    }
+
+    /**
+     * toGray(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toGray()
+     * @return Gray
+     */
+    public function toGray()
+    {
+        return $this->toRgb()->toGray();
+    }
+}

+ 37 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/ColorInterface.php

@@ -0,0 +1,37 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Color;
+
+/**
+ * Color interface.
+ */
+interface ColorInterface
+{
+    /**
+     * Converts the color to RGB.
+     *
+     * @return Rgb
+     */
+    public function toRgb();
+
+    /**
+     * Converts the color to CMYK.
+     *
+     * @return Cmyk
+     */
+    public function toCmyk();
+
+    /**
+     * Converts the color to gray.
+     *
+     * @return Gray
+     */
+    public function toGray();
+}

+ 84 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Gray.php

@@ -0,0 +1,84 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Color;
+
+use BaconQrCode\Exception;
+
+/**
+ * Gray color.
+ */
+class Gray implements ColorInterface
+{
+    /**
+     * Gray value.
+     *
+     * @var integer
+     */
+    protected $gray;
+
+    /**
+     * Creates a new gray color.
+     *
+     * A low gray value means black, while a high value means white.
+     *
+     * @param integer $gray
+     */
+    public function __construct($gray)
+    {
+        if ($gray < 0 || $gray > 100) {
+            throw new Exception\InvalidArgumentException('Gray must be between 0 and 100');
+        }
+
+        $this->gray = (int) $gray;
+    }
+
+    /**
+     * Returns the gray value.
+     *
+     * @return integer
+     */
+    public function getGray()
+    {
+        return $this->gray;
+    }
+
+    /**
+     * toRgb(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toRgb()
+     * @return Rgb
+     */
+    public function toRgb()
+    {
+        return new Rgb($this->gray * 2.55, $this->gray * 2.55, $this->gray * 2.55);
+    }
+
+    /**
+     * toCmyk(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toCmyk()
+     * @return Cmyk
+     */
+    public function toCmyk()
+    {
+        return new Cmyk(0, 0, 0, 100 - $this->gray);
+    }
+
+    /**
+     * toGray(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toGray()
+     * @return Gray
+     */
+    public function toGray()
+    {
+        return $this;
+    }
+}

+ 148 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Color/Rgb.php

@@ -0,0 +1,148 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Color;
+
+use BaconQrCode\Exception;
+
+/**
+ * RGB color.
+ */
+class Rgb implements ColorInterface
+{
+    /**
+     * Red value.
+     *
+     * @var integer
+     */
+    protected $red;
+
+    /**
+     * Green value.
+     *
+     * @var integer
+     */
+    protected $green;
+
+    /**
+     * Blue value.
+     *
+     * @var integer
+     */
+    protected $blue;
+
+    /**
+     * Creates a new RGB color.
+     *
+     * @param integer $red
+     * @param integer $green
+     * @param integer $blue
+     */
+    public function __construct($red, $green, $blue)
+    {
+        if ($red < 0 || $red > 255) {
+            throw new Exception\InvalidArgumentException('Red must be between 0 and 255');
+        }
+
+        if ($green < 0 || $green > 255) {
+            throw new Exception\InvalidArgumentException('Green must be between 0 and 255');
+        }
+
+        if ($blue < 0 || $blue > 255) {
+            throw new Exception\InvalidArgumentException('Blue must be between 0 and 255');
+        }
+
+        $this->red   = (int) $red;
+        $this->green = (int) $green;
+        $this->blue  = (int) $blue;
+    }
+
+    /**
+     * Returns the red value.
+     *
+     * @return integer
+     */
+    public function getRed()
+    {
+        return $this->red;
+    }
+
+    /**
+     * Returns the green value.
+     *
+     * @return integer
+     */
+    public function getGreen()
+    {
+        return $this->green;
+    }
+
+    /**
+     * Returns the blue value.
+     *
+     * @return integer
+     */
+    public function getBlue()
+    {
+        return $this->blue;
+    }
+
+    /**
+     * Returns a hexadecimal string representation of the RGB value.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return sprintf('%02x%02x%02x', $this->red, $this->green, $this->blue);
+    }
+
+    /**
+     * toRgb(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toRgb()
+     * @return Rgb
+     */
+    public function toRgb()
+    {
+        return $this;
+    }
+
+    /**
+     * toCmyk(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toCmyk()
+     * @return Cmyk
+     */
+    public function toCmyk()
+    {
+        $c = 1 - ($this->red / 255);
+        $m = 1 - ($this->green / 255);
+        $y = 1 - ($this->blue / 255);
+        $k = min($c, $m, $y);
+
+        return new Cmyk(
+            100 * ($c - $k) / (1 - $k),
+            100 * ($m - $k) / (1 - $k),
+            100 * ($y - $k) / (1 - $k),
+            100 * $k
+        );
+    }
+
+    /**
+     * toGray(): defined by ColorInterface.
+     *
+     * @see    ColorInterface::toGray()
+     * @return Gray
+     */
+    public function toGray()
+    {
+        return new Gray(($this->red * 0.21 + $this->green * 0.71 + $this->blue * 0.07) / 2.55);
+    }
+}

+ 338 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/AbstractRenderer.php

@@ -0,0 +1,338 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image;
+
+use BaconQrCode\Encoder\QrCode;
+use BaconQrCode\Renderer\Color;
+use BaconQrCode\Renderer\Image\Decorator\DecoratorInterface;
+use BaconQrCode\Exception;
+
+/**
+ * Image renderer, supporting multiple backends.
+ */
+abstract class AbstractRenderer implements RendererInterface
+{
+    /**
+     * Margin around the QR code, also known as quiet zone.
+     *
+     * @var integer
+     */
+    protected $margin = 4;
+
+    /**
+     * Requested width of the rendered image.
+     *
+     * @var integer
+     */
+    protected $width = 0;
+
+    /**
+     * Requested height of the rendered image.
+     *
+     * @var integer
+     */
+    protected $height = 0;
+
+    /**
+     * Whether dimensions should be rounded down.
+     *
+     * @var boolean
+     */
+    protected $roundDimensions = true;
+
+    /**
+     * Final width of the image.
+     *
+     * @var integer
+     */
+    protected $finalWidth;
+
+    /**
+     * Final height of the image.
+     *
+     * @var integer
+     */
+    protected $finalHeight;
+
+    /**
+     * Size of each individual block.
+     *
+     * @var integer
+     */
+    protected $blockSize;
+
+    /**
+     * Background color.
+     *
+     * @var Color\ColorInterface
+     */
+    protected $backgroundColor;
+
+    /**
+     * Whether dimensions should be rounded down
+     * 
+     * @var boolean
+     */
+    protected $floorToClosestDimension;
+
+    /**
+     * Foreground color.
+     *
+     * @var Color\ColorInterface
+     */
+    protected $foregroundColor;
+
+    /**
+     * Decorators used on QR codes.
+     *
+     * @var array
+     */
+    protected $decorators = array();
+
+    /**
+     * Sets the margin around the QR code.
+     *
+     * @param  integer $margin
+     * @return AbstractRenderer
+     * @throws Exception\InvalidArgumentException
+     */
+    public function setMargin($margin)
+    {
+        if ($margin < 0) {
+            throw new Exception\InvalidArgumentException('Margin must be equal to greater than 0');
+        }
+
+        $this->margin = (int) $margin;
+        return $this;
+    }
+
+    /**
+     * Gets the margin around the QR code.
+     *
+     * @return integer
+     */
+    public function getMargin()
+    {
+        return $this->margin;
+    }
+
+    /**
+     * Sets the height around the renderd image.
+     *
+     * If the width is smaller than the matrix width plus padding, the renderer
+     * will automatically use that as the width instead of the specified one.
+     *
+     * @param  integer $width
+     * @return AbstractRenderer
+     */
+    public function setWidth($width)
+    {
+        $this->width = (int) $width;
+        return $this;
+    }
+
+    /**
+     * Gets the width of the rendered image.
+     *
+     * @return integer
+     */
+    public function getWidth()
+    {
+        return $this->width;
+    }
+
+    /**
+     * Sets the height around the renderd image.
+     *
+     * If the height is smaller than the matrix height plus padding, the
+     * renderer will automatically use that as the height instead of the
+     * specified one.
+     *
+     * @param  integer $height
+     * @return AbstractRenderer
+     */
+    public function setHeight($height)
+    {
+        $this->height = (int) $height;
+        return $this;
+    }
+
+    /**
+     * Gets the height around the rendered image.
+     *
+     * @return integer
+     */
+    public function getHeight()
+    {
+        return $this->height;
+    }
+
+    /**
+     * Sets whether dimensions should be rounded down.
+     *
+     * @param  boolean $flag
+     * @return AbstractRenderer
+     */
+    public function setRoundDimensions($flag)
+    {
+        $this->floorToClosestDimension = $flag;
+        return $this;
+    }
+
+    /**
+     * Gets whether dimensions should be rounded down.
+     *
+     * @return boolean
+     */
+    public function shouldRoundDimensions()
+    {
+        return $this->floorToClosestDimension;
+    }
+
+    /**
+     * Sets background color.
+     *
+     * @param  Color\ColorInterface $color
+     * @return AbstractRenderer
+     */
+    public function setBackgroundColor(Color\ColorInterface $color)
+    {
+        $this->backgroundColor = $color;
+        return $this;
+    }
+
+    /**
+     * Gets background color.
+     *
+     * @return Color\ColorInterface
+     */
+    public function getBackgroundColor()
+    {
+        if ($this->backgroundColor === null) {
+            $this->backgroundColor = new Color\Gray(100);
+        }
+
+        return $this->backgroundColor;
+    }
+
+    /**
+     * Sets foreground color.
+     *
+     * @param  Color\ColorInterface $color
+     * @return AbstractRenderer
+     */
+    public function setForegroundColor(Color\ColorInterface $color)
+    {
+        $this->foregroundColor = $color;
+        return $this;
+    }
+
+    /**
+     * Gets foreground color.
+     *
+     * @return Color\ColorInterface
+     */
+    public function getForegroundColor()
+    {
+        if ($this->foregroundColor === null) {
+            $this->foregroundColor = new Color\Gray(0);
+        }
+
+        return $this->foregroundColor;
+    }
+
+    /**
+     * Adds a decorator to the renderer.
+     *
+     * @param  DecoratorInterface $decorator
+     * @return AbstractRenderer
+     */
+    public function addDecorator(DecoratorInterface $decorator)
+    {
+        $this->decorators[] = $decorator;
+        return $this;
+    }
+
+    /**
+     * render(): defined by RendererInterface.
+     *
+     * @see    RendererInterface::render()
+     * @param  QrCode $qrCode
+     * @return string
+     */
+    public function render(QrCode $qrCode)
+    {
+        $input        = $qrCode->getMatrix();
+        $inputWidth   = $input->getWidth();
+        $inputHeight  = $input->getHeight();
+        $qrWidth      = $inputWidth + ($this->getMargin() << 1);
+        $qrHeight     = $inputHeight + ($this->getMargin() << 1);
+        $outputWidth  = max($this->getWidth(), $qrWidth);
+        $outputHeight = max($this->getHeight(), $qrHeight);
+        $multiple     = (int) min($outputWidth / $qrWidth, $outputHeight / $qrHeight);
+
+        if ($this->shouldRoundDimensions()) {
+            $outputWidth  -= $outputWidth % $multiple;
+            $outputHeight -= $outputHeight % $multiple;
+        }
+
+        // Padding includes both the quiet zone and the extra white pixels to
+        // accommodate the requested dimensions. For example, if input is 25x25
+        // the QR will be 33x33 including the quiet zone. If the requested size
+        // is 200x160, the multiple will be 4, for a QR of 132x132. These will
+        // handle all the padding from 100x100 (the actual QR) up to 200x160.
+        $leftPadding = (int) (($outputWidth - ($inputWidth * $multiple)) / 2);
+        $topPadding  = (int) (($outputHeight - ($inputHeight * $multiple)) / 2);
+
+        // Store calculated parameters
+        $this->finalWidth  = $outputWidth;
+        $this->finalHeight = $outputHeight;
+        $this->blockSize   = $multiple;
+
+        $this->init();
+        $this->addColor('background', $this->getBackgroundColor());
+        $this->addColor('foreground', $this->getForegroundColor());
+        $this->drawBackground('background');
+
+        foreach ($this->decorators as $decorator) {
+            $decorator->preProcess(
+                $qrCode,
+                $this,
+                $outputWidth,
+                $outputHeight,
+                $leftPadding,
+                $topPadding,
+                $multiple
+            );
+        }
+
+        for ($inputY = 0, $outputY = $topPadding; $inputY < $inputHeight; $inputY++, $outputY += $multiple) {
+            for ($inputX = 0, $outputX = $leftPadding; $inputX < $inputWidth; $inputX++, $outputX += $multiple) {
+                if ($input->get($inputX, $inputY) === 1) {
+                    $this->drawBlock($outputX, $outputY, 'foreground');
+                }
+            }
+        }
+
+        foreach ($this->decorators as $decorator) {
+            $decorator->postProcess(
+                $qrCode,
+                $this,
+                $outputWidth,
+                $outputHeight,
+                $leftPadding,
+                $topPadding,
+                $multiple
+            );
+        }
+
+        return $this->getByteStream();
+    }
+}

+ 63 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/DecoratorInterface.php

@@ -0,0 +1,63 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image\Decorator;
+
+use BaconQrCode\Encoder\QrCode;
+use BaconQrCode\Renderer\Image\RendererInterface;
+
+/**
+ * Decorator interface.
+ */
+interface DecoratorInterface
+{
+    /**
+     * Pre-process a QR code.
+     *
+     * @param  QrCode            $qrCode
+     * @param  RendererInterface $renderer
+     * @param  integer           $outputWidth
+     * @param  integer           $outputHeight
+     * @param  integer           $leftPadding
+     * @param  integer           $topPadding
+     * @param  integer           $multiple
+     * @return void
+     */
+    public function preProcess(
+        QrCode $qrCode,
+        RendererInterface $renderer,
+        $outputWidth,
+        $outputHeight,
+        $leftPadding,
+        $topPadding,
+        $multiple
+    );
+
+    /**
+     * Post-process a QR code.
+     *
+     * @param  QrCode            $qrCode
+     * @param  RendererInterface $renderer
+     * @param  integer           $outputWidth
+     * @param  integer           $outputHeight
+     * @param  integer           $leftPadding
+     * @param  integer           $topPadding
+     * @param  integer           $multiple
+     * @return void
+     */
+    public function postProcess(
+        QrCode $qrCode,
+        RendererInterface $renderer,
+        $outputWidth,
+        $outputHeight,
+        $leftPadding,
+        $topPadding,
+        $multiple
+    );
+}

+ 210 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Decorator/FinderPattern.php

@@ -0,0 +1,210 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image\Decorator;
+
+use BaconQrCode\Encoder\QrCode;
+use BaconQrCode\Renderer\Image\RendererInterface;
+use BaconQrCode\Renderer\Color;
+
+/**
+ * Finder pattern decorator.
+ */
+class FinderPattern implements DecoratorInterface
+{
+    /**
+     * @var Color\ColorInterface
+     */
+    protected $innerColor;
+
+    /**
+     * @varColor\ColorInterface
+     */
+    protected $outerColor;
+
+    /**
+     * Outer position detection pattern.
+     *
+     * @var array
+     */
+    protected static $outerPositionDetectionPattern = array(
+        array(1, 1, 1, 1, 1, 1, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 0, 0, 0, 0, 0, 1),
+        array(1, 1, 1, 1, 1, 1, 1),
+    );
+
+    /**
+     * Inner position detection pattern.
+     *
+     * @var array
+     */
+    protected static $innerPositionDetectionPattern = array(
+        array(0, 0, 0, 0, 0, 0, 0),
+        array(0, 0, 0, 0, 0, 0, 0),
+        array(0, 0, 1, 1, 1, 0, 0),
+        array(0, 0, 1, 1, 1, 0, 0),
+        array(0, 0, 1, 1, 1, 0, 0),
+        array(0, 0, 0, 0, 0, 0, 0),
+        array(0, 0, 0, 0, 0, 0, 0),
+    );
+
+    /**
+     * Sets outer color.
+     *
+     * @param  Color\ColorInterface $color
+     * @return FinderPattern
+     */
+    public function setOuterColor(Color\ColorInterface $color)
+    {
+        $this->outerColor = $color;
+        return $this;
+    }
+
+    /**
+     * Gets outer color.
+     *
+     * @return Color\ColorInterface
+     */
+    public function getOuterColor()
+    {
+        if ($this->outerColor === null) {
+            $this->outerColor = new Color\Gray(100);
+        }
+
+        return $this->outerColor;
+    }
+
+    /**
+     * Sets inner color.
+     *
+     * @param  Color\ColorInterface $color
+     * @return FinderPattern
+     */
+    public function setInnerColor(Color\ColorInterface $color)
+    {
+        $this->innerColor = $color;
+        return $this;
+    }
+
+    /**
+     * Gets inner color.
+     *
+     * @return Color\ColorInterface
+     */
+    public function getInnerColor()
+    {
+        if ($this->innerColor === null) {
+            $this->innerColor = new Color\Gray(0);
+        }
+
+        return $this->innerColor;
+    }
+
+    /**
+     * preProcess(): defined by DecoratorInterface.
+     *
+     * @see    DecoratorInterface::preProcess()
+     * @param  QrCode            $qrCode
+     * @param  RendererInterface $renderer
+     * @param  integer           $outputWidth
+     * @param  integer           $outputHeight
+     * @param  integer           $leftPadding
+     * @param  integer           $topPadding
+     * @param  integer           $multiple
+     * @return void
+     */
+    public function preProcess(
+        QrCode $qrCode,
+        RendererInterface $renderer,
+        $outputWidth,
+        $outputHeight,
+        $leftPadding,
+        $topPadding,
+        $multiple
+    ) {
+        $matrix    = $qrCode->getMatrix();
+        $positions = array(
+            array(0, 0),
+            array($matrix->getWidth() - 7, 0),
+            array(0, $matrix->getHeight() - 7),
+        );
+
+        foreach (self::$outerPositionDetectionPattern as $y => $row) {
+            foreach ($row as $x => $isSet) {
+                foreach ($positions as $position) {
+                    $matrix->set($x + $position[0], $y + $position[1], 0);
+                }
+            }
+        }
+    }
+
+    /**
+     * postProcess(): defined by DecoratorInterface.
+     *
+     * @see    DecoratorInterface::postProcess()
+     *
+     * @param  QrCode            $qrCode
+     * @param  RendererInterface $renderer
+     * @param  integer           $outputWidth
+     * @param  integer           $outputHeight
+     * @param  integer           $leftPadding
+     * @param  integer           $topPadding
+     * @param  integer           $multiple
+     * @return void
+     */
+    public function postProcess(
+        QrCode $qrCode,
+        RendererInterface $renderer,
+        $outputWidth,
+        $outputHeight,
+        $leftPadding,
+        $topPadding,
+        $multiple
+    ) {
+        $matrix    = $qrCode->getMatrix();
+        $positions = array(
+            array(0, 0),
+            array($matrix->getWidth() - 7, 0),
+            array(0, $matrix->getHeight() - 7),
+        );
+
+        $renderer->addColor('finder-outer', $this->getOuterColor());
+        $renderer->addColor('finder-inner', $this->getInnerColor());
+
+        foreach (self::$outerPositionDetectionPattern as $y => $row) {
+            foreach ($row as $x => $isOuterSet) {
+                $isInnerSet = self::$innerPositionDetectionPattern[$y][$x];
+
+                if ($isOuterSet) {
+                    foreach ($positions as $position) {
+                        $renderer->drawBlock(
+                            $leftPadding + $x * $multiple + $position[0] * $multiple,
+                            $topPadding + $y * $multiple + $position[1] * $multiple,
+                            'finder-outer'
+                        );
+                    }
+                }
+
+                if ($isInnerSet) {
+                    foreach ($positions as $position) {
+                        $renderer->drawBlock(
+                            $leftPadding + $x * $multiple + $position[0] * $multiple,
+                            $topPadding + $y * $multiple + $position[1] * $multiple,
+                            'finder-inner'
+                        );
+                    }
+                }
+            }
+        }
+    }
+}

+ 152 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Eps.php

@@ -0,0 +1,152 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image;
+
+use BaconQrCode\Renderer\Color\ColorInterface;
+use BaconQrCode\Renderer\Color\Rgb;
+use BaconQrCode\Renderer\Color\Cmyk;
+use BaconQrCode\Renderer\Color\Gray;
+
+/**
+ * EPS backend.
+ */
+class Eps extends AbstractRenderer
+{
+    /**
+     * EPS string.
+     *
+     * @var string
+     */
+    protected $eps;
+
+    /**
+     * Colors used for drawing.
+     *
+     * @var array
+     */
+    protected $colors = array();
+
+    /**
+     * Current color.
+     *
+     * @var string
+     */
+    protected $currentColor;
+
+    /**
+     * init(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::init()
+     * @return void
+     */
+    public function init()
+    {
+        $this->eps = "%!PS-Adobe-3.0 EPSF-3.0\n"
+                   . "%%BoundingBox: 0 0 " . $this->finalWidth . " " . $this->finalHeight . "\n"
+                   . "/F { rectfill } def\n";
+    }
+
+    /**
+     * addColor(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::addColor()
+     * @param  string         $id
+     * @param  ColorInterface $color
+     * @return void
+     */
+    public function addColor($id, ColorInterface $color)
+    {
+        if (
+            !$color instanceof Rgb
+            && !$color instanceof Cmyk
+            && !$color instanceof Gray
+        ) {
+            $color = $color->toCmyk();
+        }
+
+        $this->colors[$id] = $color;
+    }
+
+    /**
+     * drawBackground(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::drawBackground()
+     * @param  string $colorId
+     * @return void
+     */
+    public function drawBackground($colorId)
+    {
+        $this->setColor($colorId);
+        $this->eps .= "0 0 " . $this->finalWidth . " " . $this->finalHeight . " F\n";
+    }
+
+    /**
+     * drawBlock(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::drawBlock()
+     * @param  integer $x
+     * @param  integer $y
+     * @param  string  $colorId
+     * @return void
+     */
+    public function drawBlock($x, $y, $colorId)
+    {
+        $this->setColor($colorId);
+        $this->eps .= $x . " " . ($this->finalHeight - $y - $this->blockSize) . " " . $this->blockSize . " " . $this->blockSize . " F\n";
+    }
+
+    /**
+     * getByteStream(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::getByteStream()
+     * @return string
+     */
+    public function getByteStream()
+    {
+        return $this->eps;
+    }
+
+    /**
+     * Sets color to use.
+     *
+     * @param  string $colorId
+     * @return void
+     */
+    protected function setColor($colorId)
+    {
+        if ($colorId !== $this->currentColor) {
+            $color = $this->colors[$colorId];
+
+            if ($color instanceof Rgb) {
+                $this->eps .= sprintf(
+                    "%F %F %F setrgbcolor\n",
+                    $color->getRed() / 100,
+                    $color->getGreen() / 100,
+                    $color->getBlue() / 100
+                );
+            } elseif ($color instanceof Cmyk) {
+                $this->eps .= sprintf(
+                    "%F %F %F %F setcmykcolor\n",
+                    $color->getCyan() / 100,
+                    $color->getMagenta() / 100,
+                    $color->getYellow() / 100,
+                    $color->getBlack() / 100
+                );
+            } elseif ($color instanceof Gray) {
+                $this->eps .= sprintf(
+                    "%F setgray\n",
+                    $color->getGray() / 100
+                );
+            }
+
+            $this->currentColor = $colorId;
+        }
+    }
+}

+ 115 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Png.php

@@ -0,0 +1,115 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image;
+
+use BaconQrCode\Exception;
+use BaconQrCode\Renderer\Color\ColorInterface;
+
+/**
+ * PNG backend.
+ */
+class Png extends AbstractRenderer
+{
+    /**
+     * Image resource used when drawing.
+     *
+     * @var resource
+     */
+    protected $image;
+
+    /**
+     * Colors used for drawing.
+     *
+     * @var array
+     */
+    protected $colors = array();
+
+    /**
+     * init(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::init()
+     * @return void
+     */
+    public function init()
+    {
+        $this->image = imagecreatetruecolor($this->finalWidth, $this->finalHeight);
+    }
+
+    /**
+     * addColor(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::addColor()
+     * @param  string         $id
+     * @param  ColorInterface $color
+     * @return void
+     * @throws Exception\RuntimeException
+     */
+    public function addColor($id, ColorInterface $color)
+    {
+        if ($this->image === null) {
+            throw new Exception\RuntimeException('Colors can only be added after init');
+        }
+
+        $color = $color->toRgb();
+
+        $this->colors[$id] = imagecolorallocate(
+            $this->image,
+            $color->getRed(),
+            $color->getGreen(),
+            $color->getBlue()
+        );
+    }
+
+    /**
+     * drawBackground(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::drawBackground()
+     * @param  string $colorId
+     * @return void
+     */
+    public function drawBackground($colorId)
+    {
+        imagefill($this->image, 0, 0, $this->colors[$colorId]);
+    }
+
+    /**
+     * drawBlock(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::drawBlock()
+     * @param  integer $x
+     * @param  integer $y
+     * @param  string  $colorId
+     * @return void
+     */
+    public function drawBlock($x, $y, $colorId)
+    {
+        imagefilledrectangle(
+            $this->image,
+            $x,
+            $y,
+            $x + $this->blockSize - 1,
+            $y + $this->blockSize - 1,
+            $this->colors[$colorId]
+        );
+    }
+
+    /**
+     * getByteStream(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::getByteStream()
+     * @return string
+     */
+    public function getByteStream()
+    {
+        ob_start();
+        imagepng($this->image);
+        return ob_get_clean();
+    }
+}

+ 61 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/RendererInterface.php

@@ -0,0 +1,61 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image;
+
+use BaconQrCode\Renderer\Color\ColorInterface;
+use BaconQrCode\Renderer\RendererInterface as GeneralRendererInterface;
+
+/**
+ * Renderer interface.
+ */
+interface RendererInterface extends GeneralRendererInterface
+{
+    /**
+     * Initiates the drawing area.
+     *
+     * @return void
+     */
+    public function init();
+
+    /**
+     * Adds a color to the drawing area.
+     *
+     * @param  string         $id
+     * @param  ColorInterface $color
+     * @return void
+     */
+    public function addColor($id, ColorInterface $color);
+
+    /**
+     * Draws the background.
+     *
+     * @param  string $colorId
+     * @return void
+     */
+    public function drawBackground($colorId);
+
+    /**
+     * Draws a block at a specified position.
+     *
+     * @param  integer $x
+     * @param  integer $y
+     * @param  string  $colorId
+     * @return void
+     */
+    public function drawBlock($x, $y, $colorId);
+
+    /**
+     * Returns the byte stream representing the QR code.
+     *
+     * @return string
+     */
+    public function getByteStream();
+
+}

+ 146 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Image/Svg.php

@@ -0,0 +1,146 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Image;
+
+use BaconQrCode\Exception;
+use BaconQrCode\Renderer\Color\ColorInterface;
+use SimpleXMLElement;
+
+/**
+ * SVG backend.
+ */
+class Svg extends AbstractRenderer
+{
+    /**
+     * SVG resource.
+     *
+     * @var SimpleXMLElement
+     */
+    protected $svg;
+
+    /**
+     * Colors used for drawing.
+     *
+     * @var array
+     */
+    protected $colors = array();
+
+    /**
+     * Prototype IDs.
+     *
+     * @var array
+     */
+    protected $prototypeIds = array();
+
+    /**
+     * init(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::init()
+     * @return void
+     */
+    public function init()
+    {
+        $this->svg = new SimpleXMLElement(
+            '<?xml version="1.0" encoding="UTF-8"?>'
+            . '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"/>'
+        );
+        $this->svg->addAttribute('version', '1.1');
+        $this->svg->addAttribute('width', $this->finalWidth . 'px');
+        $this->svg->addAttribute('height', $this->finalHeight . 'px');
+        $this->svg->addAttribute('viewBox', '0 0 ' . $this->finalWidth . ' ' . $this->finalHeight);
+        $this->svg->addChild('defs');
+    }
+
+    /**
+     * addColor(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::addColor()
+     * @param  string         $id
+     * @param  ColorInterface $color
+     * @return void
+     * @throws Exception\InvalidArgumentException
+     */
+    public function addColor($id, ColorInterface $color)
+    {
+        $this->colors[$id] = (string) $color->toRgb();
+    }
+
+    /**
+     * drawBackground(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::drawBackground()
+     * @param  string $colorId
+     * @return void
+     */
+    public function drawBackground($colorId)
+    {
+        $rect = $this->svg->addChild('rect');
+        $rect->addAttribute('x', 0);
+        $rect->addAttribute('y', 0);
+        $rect->addAttribute('width', $this->finalWidth);
+        $rect->addAttribute('height', $this->finalHeight);
+        $rect->addAttribute('fill', '#' . $this->colors[$colorId]);
+    }
+
+    /**
+     * drawBlock(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::drawBlock()
+     * @param  integer $x
+     * @param  integer $y
+     * @param  string  $colorId
+     * @return void
+     */
+    public function drawBlock($x, $y, $colorId)
+    {
+        $use = $this->svg->addChild('use');
+        $use->addAttribute('x', $x);
+        $use->addAttribute('y', $y);
+        $use->addAttribute(
+            'xlink:href',
+            $this->getRectPrototypeId($colorId),
+            'http://www.w3.org/1999/xlink'
+        );
+    }
+
+    /**
+     * getByteStream(): defined by RendererInterface.
+     *
+     * @see    ImageRendererInterface::getByteStream()
+     * @return string
+     */
+    public function getByteStream()
+    {
+        return $this->svg->asXML();
+    }
+
+    /**
+     * Get the prototype ID for a color.
+     *
+     * @param  integer $colorId
+     * @return string
+     */
+    protected function getRectPrototypeId($colorId)
+    {
+        if (!isset($this->prototypeIds[$colorId])) {
+            $id = 'r' . dechex(count($this->prototypeIds));
+
+            $rect = $this->svg->defs->addChild('rect');
+            $rect->addAttribute('id', $id);
+            $rect->addAttribute('width', $this->blockSize);
+            $rect->addAttribute('height', $this->blockSize);
+            $rect->addAttribute('fill', '#' . $this->colors[$colorId]);
+
+            $this->prototypeIds[$colorId] = '#' . $id;
+        }
+
+        return $this->prototypeIds[$colorId];
+    }
+}

+ 26 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/RendererInterface.php

@@ -0,0 +1,26 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer;
+
+use BaconQrCode\Encoder\QrCode;
+
+/**
+ * Renderer interface.
+ */
+interface RendererInterface
+{
+    /**
+     * Renders a QR code.
+     *
+     * @param  QrCode $qrCode
+     * @return string
+     */
+    public function render(QrCode $qrCode);
+}

+ 91 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Html.php

@@ -0,0 +1,91 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Text;
+
+use BaconQrCode\Encoder\QrCode;
+
+/**
+ * Html renderer.
+ */
+class Html extends Plain
+{
+    /**
+     * HTML CSS class attribute value.
+     *
+     * @var string
+     */
+    protected $class = '';
+
+    /**
+     * HTML CSS style definition for the code element.
+     *
+     * @var string
+     */
+    protected $style = 'font-family: monospace; line-height: 0.65em; letter-spacing: -1px';
+
+    /**
+     * Set CSS class name.
+     *
+     * @param string $class
+     */
+    public function setClass($class)
+    {
+        $this->class = $class;
+    }
+
+    /**
+     * Get CSS class name.
+     *
+     * @return string
+     */
+    public function getClass()
+    {
+        return $this->class;
+    }
+
+    /**
+     * Set CSS style value.
+     *
+     * @param string $style
+     */
+    public function setStyle($style)
+    {
+        $this->style = $style;
+    }
+
+    /**
+     * Get CSS style value.
+     *
+     * @return string
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * render(): defined by RendererInterface.
+     *
+     * @see    RendererInterface::render()
+     * @param  QrCode $qrCode
+     * @return string
+     */
+    public function render(QrCode $qrCode)
+    {
+        $textCode = parent::render($qrCode);
+
+        $result = '<pre'
+                . ' style="' . htmlspecialchars($this->style, ENT_QUOTES, 'utf-8') . '"'
+                . ' class="' . htmlspecialchars($this->class, ENT_QUOTES, 'utf-8') . '"'
+                . '>' . $textCode . '</pre>';
+
+        return $result;
+    }
+}

+ 150 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Renderer/Text/Plain.php

@@ -0,0 +1,150 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Renderer\Text;
+
+use BaconQrCode\Exception;
+use BaconQrCode\Encoder\QrCode;
+use BaconQrCode\Renderer\RendererInterface;
+
+/**
+ * Plaintext renderer.
+ */
+class Plain implements RendererInterface
+{
+    /**
+     * Margin around the QR code, also known as quiet zone.
+     *
+     * @var integer
+     */
+    protected $margin = 1;
+
+    /**
+     * Char used for full block.
+     *
+     * UTF-8 FULL BLOCK (U+2588)
+     *
+     * @var  string
+     * @link http://www.fileformat.info/info/unicode/char/2588/index.htm
+     */
+    protected $fullBlock = "\xE2\x96\x88";
+
+    /**
+     * Char used for empty space
+     *
+     * @var string
+     */
+    protected $emptyBlock = ' ';
+
+    /**
+     * Set char used as full block (occupied space, "black").
+     *
+     * @param string $fullBlock
+     */
+    public function setFullBlock($fullBlock)
+    {
+        $this->fullBlock = $fullBlock;
+    }
+
+    /**
+     * Get char used as full block (occupied space, "black").
+     *
+     * @return string
+     */
+    public function getFullBlock()
+    {
+        return $this->fullBlock;
+    }
+
+    /**
+     * Set char used as empty block (empty space, "white").
+     *
+     * @param string $emptyBlock
+     */
+    public function setEmptyBlock($emptyBlock)
+    {
+        $this->emptyBlock = $emptyBlock;
+    }
+
+    /**
+     * Get char used as empty block (empty space, "white").
+     *
+     * @return string
+     */
+    public function getEmptyBlock()
+    {
+        return $this->emptyBlock;
+    }
+
+    /**
+     * Sets the margin around the QR code.
+     *
+     * @param  integer $margin
+     * @return AbstractRenderer
+     * @throws Exception\InvalidArgumentException
+     */
+    public function setMargin($margin)
+    {
+        if ($margin < 0) {
+            throw new Exception\InvalidArgumentException('Margin must be equal to greater than 0');
+        }
+
+        $this->margin = (int) $margin;
+
+        return $this;
+    }
+
+    /**
+     * Gets the margin around the QR code.
+     *
+     * @return integer
+     */
+    public function getMargin()
+    {
+        return $this->margin;
+    }
+
+    /**
+     * render(): defined by RendererInterface.
+     *
+     * @see    RendererInterface::render()
+     * @param  QrCode $qrCode
+     * @return string
+     */
+    public function render(QrCode $qrCode)
+    {
+        $result = '';
+        $matrix = $qrCode->getMatrix();
+        $width  = $matrix->getWidth();
+
+        // Top margin
+        for ($x = 0; $x < $this->margin; $x++) {
+            $result .= str_repeat($this->emptyBlock, $width + 2 * $this->margin)."\n";
+        }
+
+        // Body
+        $array = $matrix->getArray();
+
+        foreach ($array as $row) {
+            $result .= str_repeat($this->emptyBlock, $this->margin); // left margin
+            foreach ($row as $byte) {
+                $result .= $byte ? $this->fullBlock : $this->emptyBlock;
+            }
+            $result .= str_repeat($this->emptyBlock, $this->margin); // right margin
+            $result .= "\n";
+        }
+
+        // Bottom margin
+        for ($x = 0; $x < $this->margin; $x++) {
+            $result .= str_repeat($this->emptyBlock, $width + 2 * $this->margin)."\n";
+        }
+
+        return $result;
+    }
+}

+ 105 - 0
vendor/bacon/bacon-qr-code/src/BaconQrCode/Writer.php

@@ -0,0 +1,105 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode;
+
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Encoder\Encoder;
+use BaconQrCode\Exception;
+use BaconQrCode\Renderer\RendererInterface;
+
+/**
+ * QR code writer.
+ */
+class Writer
+{
+    /**
+     * Renderer instance.
+     *
+     * @var RendererInterface
+     */
+    protected $renderer;
+
+    /**
+     * Creates a new writer with a specific renderer.
+     *
+     * @param RendererInterface $renderer
+     */
+    public function __construct(RendererInterface $renderer)
+    {
+        $this->renderer = $renderer;
+    }
+
+    /**
+     * Sets the renderer used to create a byte stream.
+     *
+     * @param  RendererInterface $renderer
+     * @return Writer
+     */
+    public function setRenderer(RendererInterface $renderer)
+    {
+        $this->renderer = $renderer;
+        return $this;
+    }
+
+    /**
+     * Gets the renderer used to create a byte stream.
+     *
+     * @return RendererInterface
+     */
+    public function getRenderer()
+    {
+        return $this->renderer;
+    }
+
+    /**
+     * Writes QR code and returns it as string.
+     *
+     * Content is a string which *should* be encoded in UTF-8, in case there are
+     * non ASCII-characters present.
+     *
+     * @param  string  $content
+     * @param  string  $encoding
+     * @param  integer $ecLevel
+     * @return string
+     * @throws Exception\InvalidArgumentException
+     */
+    public function writeString(
+        $content,
+        $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
+        $ecLevel = ErrorCorrectionLevel::L
+    ) {
+        if (strlen($content) === 0) {
+            throw new Exception\InvalidArgumentException('Found empty contents');
+        }
+
+        $qrCode = Encoder::encode($content, new ErrorCorrectionLevel($ecLevel), $encoding);
+
+        return $this->getRenderer()->render($qrCode);
+    }
+
+    /**
+     * Writes QR code to a file.
+     *
+     * @see    Writer::writeString()
+     * @param  string  $content
+     * @param  string  $filename
+     * @param  string  $encoding
+     * @param  integer $ecLevel
+     * @return void
+     */
+    public function writeFile(
+        $content,
+        $filename,
+        $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
+        $ecLevel = ErrorCorrectionLevel::L
+    ) {
+        file_put_contents($filename, $this->writeString($content, $encoding, $ecLevel));
+    }
+}

+ 201 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitArrayTest.php

@@ -0,0 +1,201 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class BitArrayTest extends TestCase
+{
+    public function testGetSet()
+    {
+        $array = new BitArray(33);
+
+        for ($i = 0; $i < 33; $i++) {
+            $this->assertFalse($array->get($i));
+            $array->set($i);
+            $this->assertTrue($array->get($i));
+        }
+    }
+
+    public function testGetNextSet1()
+    {
+        $array = new BitArray(32);
+
+        for ($i = 0; $i < $array->getSize(); $i++) {
+            $this->assertEquals($i, 32, '', $array->getNextSet($i));
+        }
+
+        $array = new BitArray(33);
+
+        for ($i = 0; $i < $array->getSize(); $i++) {
+            $this->assertEquals($i, 33, '', $array->getNextSet($i));
+        }
+    }
+
+    public function testGetNextSet2()
+    {
+        $array = new BitArray(33);
+
+        for ($i = 0; $i < $array->getSize(); $i++) {
+            $this->assertEquals($i, $i <= 31 ? 31 : 33, '', $array->getNextSet($i));
+        }
+
+        $array = new BitArray(33);
+
+        for ($i = 0; $i < $array->getSize(); $i++) {
+            $this->assertEquals($i, 32, '', $array->getNextSet($i));
+        }
+    }
+
+    public function testGetNextSet3()
+    {
+        $array = new BitArray(63);
+        $array->set(31);
+        $array->set(32);
+
+        for ($i = 0; $i < $array->getSize(); $i++) {
+            if ($i <= 31) {
+                $expected = 31;
+            } elseif ($i <= 32) {
+                $expected = 32;
+            } else {
+                $expected = 63;
+            }
+
+            $this->assertEquals($i, $expected, '', $array->getNextSet($i));
+        }
+    }
+
+    public function testGetNextSet4()
+    {
+        $array = new BitArray(63);
+        $array->set(33);
+        $array->set(40);
+
+        for ($i = 0; $i < $array->getSize(); $i++) {
+            if ($i <= 33) {
+                $expected = 33;
+            } elseif ($i <= 40) {
+                $expected = 40;
+            } else {
+                $expected = 63;
+            }
+
+            $this->assertEquals($i, $expected, '', $array->getNextSet($i));
+        }
+    }
+
+    public function testGetNextSet5()
+    {
+        if (defined('MT_RAND_PHP')) {
+            mt_srand(0xdeadbeef, MT_RAND_PHP);
+        } else {
+            mt_srand(0xdeadbeef);
+        }
+
+        for ($i = 0; $i < 10; $i++) {
+            $array  = new BitArray(mt_rand(1, 100));
+            $numSet = mt_rand(0, 19);
+
+            for ($j = 0; $j < $numSet; $j++) {
+                $array->set(mt_rand(0, $array->getSize() - 1));
+            }
+
+            $numQueries = mt_rand(0, 19);
+
+            for ($j = 0; $j < $numQueries; $j++) {
+                $query    = mt_rand(0, $array->getSize() - 1);
+                $expected = $query;
+
+                while ($expected < $array->getSize() && !$array->get($expected)) {
+                    $expected++;
+                }
+
+                $actual = $array->getNextSet($query);
+
+                if ($actual !== $expected) {
+                    $array->getNextSet($query);
+                }
+
+                $this->assertEquals($expected, $actual);
+            }
+        }
+    }
+
+    public function testSetBulk()
+    {
+        $array = new BitArray(64);
+        $array->setBulk(32, 0xFFFF0000);
+
+        for ($i = 0; $i < 48; $i++) {
+            $this->assertFalse($array->get($i));
+        }
+
+        for ($i = 48; $i < 64; $i++) {
+            $this->assertTrue($array->get($i));
+        }
+    }
+
+    public function testClear()
+    {
+        $array = new BitArray(32);
+
+        for ($i = 0; $i < 32; $i++) {
+            $array->set($i);
+        }
+
+        $array->clear();
+
+        for ($i = 0; $i < 32; $i++) {
+            $this->assertFalse($array->get($i));
+        }
+    }
+
+    public function testGetArray()
+    {
+        $array = new BitArray(64);
+        $array->set(0);
+        $array->set(63);
+
+        $ints = $array->getBitArray();
+
+        $this->assertEquals(1, $ints[0]);
+        $this->assertEquals(0x80000000, $ints[1]);
+    }
+
+    public function testIsRange()
+    {
+        $array = new BitArray(64);
+        $this->assertTrue($array->isRange(0, 64, false));
+        $this->assertFalse($array->isRange(0, 64, true));
+
+        $array->set(32);
+        $this->assertTrue($array->isRange(32, 33, true));
+
+        $array->set(31);
+        $this->assertTrue($array->isRange(31, 33, true));
+
+        $array->set(34);
+        $this->assertFalse($array->isRange(31, 35, true));
+
+        for ($i = 0; $i < 31; $i++) {
+            $array->set($i);
+        }
+
+        $this->assertTrue($array->isRange(0, 33, true));
+
+        for ($i = 33; $i < 64; $i++) {
+            $array->set($i);
+        }
+
+        $this->assertTrue($array->isRange(0, 64, true));
+        $this->assertFalse($array->isRange(0, 64, false));
+    }
+}

+ 119 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitMatrixTest.php

@@ -0,0 +1,119 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class BitMatrixTest extends TestCase
+{
+    public function testGetSet()
+    {
+        $matrix = new BitMatrix(33);
+        $this->assertEquals(33, $matrix->getHeight());
+
+        for ($y = 0; $y < 33; $y++) {
+            for ($x = 0; $x < 33; $x++) {
+                if ($y * $x % 3 === 0) {
+                    $matrix->set($x, $y);
+                }
+            }
+        }
+
+        for ($y = 0; $y < 33; $y++) {
+            for ($x = 0; $x < 33; $x++) {
+                $this->assertEquals($x * $y % 3 === 0, $matrix->get($x, $y));
+            }
+        }
+    }
+
+    public function testSetRegion()
+    {
+        $matrix = new BitMatrix(5);
+        $matrix->setRegion(1, 1, 3, 3);
+
+        for ($y = 0; $y < 5; $y++) {
+            for ($x = 0; $x < 5; $x++) {
+                $this->assertEquals($y >= 1 && $y <= 3 && $x >= 1 && $x <= 3, $matrix->get($x, $y));
+            }
+        }
+    }
+
+    public function testRectangularMatrix()
+    {
+        $matrix = new BitMatrix(75, 20);
+        $this->assertEquals(75, $matrix->getWidth());
+        $this->assertEquals(20, $matrix->getHeight());
+
+        $matrix->set(10, 0);
+        $matrix->set(11, 1);
+        $matrix->set(50, 2);
+        $matrix->set(51, 3);
+        $matrix->flip(74, 4);
+        $matrix->flip(0, 5);
+
+        $this->assertTrue($matrix->get(10, 0));
+        $this->assertTrue($matrix->get(11, 1));
+        $this->assertTrue($matrix->get(50, 2));
+        $this->assertTrue($matrix->get(51, 3));
+        $this->assertTrue($matrix->get(74, 4));
+        $this->assertTrue($matrix->get(0, 5));
+
+        $matrix->flip(50, 2);
+        $matrix->flip(51, 3);
+
+        $this->assertFalse($matrix->get(50, 2));
+        $this->assertFalse($matrix->get(51, 3));
+    }
+
+    public function testRectangularSetRegion()
+    {
+        $matrix = new BitMatrix(320, 240);
+        $this->assertEquals(320, $matrix->getWidth());
+        $this->assertEquals(240, $matrix->getHeight());
+
+        $matrix->setRegion(105, 22, 80, 12);
+
+        for ($y = 0; $y < 240; $y++) {
+            for ($x = 0; $x < 320; $x++) {
+                $this->assertEquals($y >= 22 && $y < 34 && $x >= 105 && $x < 185, $matrix->get($x, $y));
+            }
+        }
+    }
+
+    public function testGetRow()
+    {
+        $matrix = new BitMatrix(102, 5);
+
+        for ($x = 0; $x < 102; $x++) {
+            if ($x & 3 === 0) {
+                $matrix->set($x, 2);
+            }
+        }
+
+        $array1 = $matrix->getRow(2, null);
+        $this->assertEquals(102, $array1->getSize());
+
+        $array2 = new BitArray(60);
+        $array2 = $matrix->getRow(2, $array2);
+        $this->assertEquals(102, $array2->getSize());
+
+        $array3 = new BitArray(200);
+        $array3 = $matrix->getRow(2, $array3);
+        $this->assertEquals(200, $array3->getSize());
+
+        for ($x = 0; $x < 102; $x++) {
+            $on = ($x & 3 === 0);
+
+            $this->assertEquals($on, $array1->get($x));
+            $this->assertEquals($on, $array2->get($x));
+            $this->assertEquals($on, $array3->get($x));
+        }
+    }
+}

+ 30 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/BitUtilsTest.php

@@ -0,0 +1,30 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class BitUtilsTest extends TestCase
+{
+    public function testUnsignedRightShift()
+    {
+        $this->assertEquals(1, BitUtils::unsignedRightShift(1, 0));
+        $this->assertEquals(1, BitUtils::unsignedRightShift(10, 3));
+        $this->assertEquals(536870910, BitUtils::unsignedRightShift(-10, 3));
+    }
+
+    public function testNumberOfTrailingZeros()
+    {
+        $this->assertEquals(32, BitUtils::numberOfTrailingZeros(0));
+        $this->assertEquals(1, BitUtils::numberOfTrailingZeros(10));
+        $this->assertEquals(0, BitUtils::numberOfTrailingZeros(15));
+        $this->assertEquals(2, BitUtils::numberOfTrailingZeros(20));
+    }
+}

+ 40 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ErrorCorrectionLevelTest.php

@@ -0,0 +1,40 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class ErrorCorrectionLevelTest extends TestCase
+{
+    public function testCreationThrowsNoException()
+    {
+        new ErrorCorrectionLevel(ErrorCorrectionLevel::M);
+        new ErrorCorrectionLevel(ErrorCorrectionLevel::L);
+        new ErrorCorrectionLevel(ErrorCorrectionLevel::H);
+        new ErrorCorrectionLevel(ErrorCorrectionLevel::Q);
+    }
+
+    public function testBitsMatchConstants()
+    {
+        $this->assertEquals(0x0, ErrorCorrectionLevel::M);
+        $this->assertEquals(0x1, ErrorCorrectionLevel::L);
+        $this->assertEquals(0x2, ErrorCorrectionLevel::H);
+        $this->assertEquals(0x3, ErrorCorrectionLevel::Q);
+    }
+
+    public function testInvalidErrorCorrectionLevelThrowsException()
+    {
+        $this->setExpectedException(
+            'BaconQrCode\Exception\UnexpectedValueException',
+            'Value not a const in enum BaconQrCode\Common\ErrorCorrectionLevel'
+        );
+        new ErrorCorrectionLevel(4);
+    }
+}

+ 104 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/FormatInformationTest.php

@@ -0,0 +1,104 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class FormatInformationTest extends TestCase
+{
+    protected $maskedTestFormatInfo = 0x2bed;
+    protected $unmaskedTestFormatInfo;
+
+    public function setUp()
+    {
+        $this->unmaskedTestFormatInfo = $this->maskedTestFormatInfo ^ 0x5412;
+    }
+
+
+    public function testBitsDiffering()
+    {
+        $this->assertEquals(0, FormatInformation::numBitsDiffering(1, 1));
+        $this->assertEquals(1, FormatInformation::numBitsDiffering(0, 2));
+        $this->assertEquals(2, FormatInformation::numBitsDiffering(1, 2));
+        $this->assertEquals(32, FormatInformation::numBitsDiffering(-1, 0));
+    }
+
+    public function testDecode()
+    {
+        $expected = FormatInformation::decodeFormatInformation(
+            $this->maskedTestFormatInfo,
+            $this->maskedTestFormatInfo
+        );
+
+        $this->assertNotNull($expected);
+        $this->assertEquals(7, $expected->getDataMask());
+        $this->assertEquals(ErrorCorrectionLevel::Q, $expected->getErrorCorrectionLevel()->get());
+
+        $this->assertEquals(
+            $expected,
+            FormatInformation::decodeFormatInformation(
+                $this->unmaskedTestFormatInfo,
+                $this->maskedTestFormatInfo
+            )
+        );
+    }
+
+    public function testDecodeWithBitDifference()
+    {
+        $expected = FormatInformation::decodeFormatInformation(
+            $this->maskedTestFormatInfo,
+            $this->maskedTestFormatInfo
+        );
+
+        $this->assertEquals(
+            $expected,
+            FormatInformation::decodeFormatInformation(
+                $this->maskedTestFormatInfo ^ 0x1,
+                $this->maskedTestFormatInfo ^ 0x1
+            )
+        );
+        $this->assertEquals(
+            $expected,
+            FormatInformation::decodeFormatInformation(
+                $this->maskedTestFormatInfo ^ 0x3,
+                $this->maskedTestFormatInfo ^ 0x3
+            )
+        );
+        $this->assertEquals(
+            $expected,
+            FormatInformation::decodeFormatInformation(
+                $this->maskedTestFormatInfo ^ 0x7,
+                $this->maskedTestFormatInfo ^ 0x7
+            )
+        );
+        $this->assertNull(
+            FormatInformation::decodeFormatInformation(
+                $this->maskedTestFormatInfo ^ 0xf,
+                $this->maskedTestFormatInfo ^ 0xf
+            )
+        );
+    }
+
+    public function testDecodeWithMisRead()
+    {
+        $expected = FormatInformation::decodeFormatInformation(
+            $this->maskedTestFormatInfo,
+            $this->maskedTestFormatInfo
+        );
+
+        $this->assertEquals(
+            $expected,
+            FormatInformation::decodeFormatInformation(
+                $this->maskedTestFormatInfo ^ 0x3,
+                $this->maskedTestFormatInfo ^ 0xf
+            )
+        );
+    }
+}

+ 42 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ModeTest.php

@@ -0,0 +1,42 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class ModeTest extends TestCase
+{
+    public function testCreationThrowsNoException()
+    {
+        new Mode(Mode::TERMINATOR);
+        new Mode(Mode::NUMERIC);
+        new Mode(Mode::ALPHANUMERIC);
+        new Mode(Mode::BYTE);
+        new Mode(Mode::KANJI);
+    }
+
+    public function testBitsMatchConstants()
+    {
+        $this->assertEquals(0x0, Mode::TERMINATOR);
+        $this->assertEquals(0x1, Mode::NUMERIC);
+        $this->assertEquals(0x2, Mode::ALPHANUMERIC);
+        $this->assertEquals(0x4, Mode::BYTE);
+        $this->assertEquals(0x8, Mode::KANJI);
+    }
+
+    public function testInvalidModeThrowsException()
+    {
+        $this->setExpectedException(
+            'BaconQrCode\Exception\UnexpectedValueException',
+            'Value not a const in enum BaconQrCode\Common\Mode'
+        );
+        new Mode(10);
+    }
+}

+ 111 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/ReedSolomonCodecTest.php

@@ -0,0 +1,111 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+use SplFixedArray;
+
+class ReedSolomonTest extends TestCase
+{
+    public static function tabProvider()
+    {
+        return array(
+            array(2, 0x7,   1, 1, 1),
+            array(3, 0xb,   1, 1, 2),
+            array(4, 0x13,  1, 1, 4),
+            array(5, 0x25,  1, 1, 6),
+            array(6, 0x43,  1, 1, 8),
+            array(7, 0x89,  1, 1, 10),
+            array(8, 0x11d, 1, 1, 32),
+        );
+    }
+
+    /**
+     * @dataProvider tabProvider
+     * @param        integer $symbolSize
+     * @param        integer $generatorPoly
+     * @param        integer $firstRoot
+     * @param        integer $primitive
+     * @param        integer $numRoots
+     * @return       void
+     */
+    public function testCodec($symbolSize, $generatorPoly, $firstRoot, $primitive, $numRoots)
+    {
+        if (defined('MT_RAND_PHP')) {
+            mt_srand(0xdeadbeef, MT_RAND_PHP);
+        } else {
+            mt_srand(0xdeadbeef);
+        }
+
+        $blockSize = (1 << $symbolSize) - 1;
+        $dataSize  = $blockSize - $numRoots;
+        $codec     = new ReedSolomonCodec($symbolSize, $generatorPoly, $firstRoot, $primitive, $numRoots, 0);
+
+        for ($errors = 0; $errors <= $numRoots / 2; $errors++) {
+            // Load block with random data and encode
+            $block = SplFixedArray::fromArray(array_fill(0, $blockSize, 0), false);
+
+            for ($i = 0; $i < $dataSize; $i++) {
+                $block[$i] = mt_rand(0, $blockSize);
+            }
+
+            // Make temporary copy
+            $tBlock         = clone $block;
+            $parity         = SplFixedArray::fromArray(array_fill(0, $numRoots, 0), false);
+            $errorLocations = SplFixedArray::fromArray(array_fill(0, $blockSize, 0), false);
+            $erasures       = array();
+
+            // Create parity
+            $codec->encode($block, $parity);
+
+            // Copy parity into test blocks
+            for ($i = 0; $i < $numRoots; $i++) {
+                $block[$i + $dataSize] = $parity[$i];
+                $tBlock[$i + $dataSize] = $parity[$i];
+            }
+
+            // Seed with errors
+            for ($i = 0; $i < $errors; $i++) {
+                $errorValue = mt_rand(1, $blockSize);
+
+                do {
+                    $errorLocation = mt_rand(0, $blockSize);
+                } while ($errorLocations[$errorLocation] !== 0);
+
+                $errorLocations[$errorLocation] = 1;
+
+                if (mt_rand(0, 1)) {
+                    $erasures[] = $errorLocation;
+                }
+
+                $tBlock[$errorLocation] ^= $errorValue;
+            }
+
+            $erasures = SplFixedArray::fromArray($erasures, false);
+
+            // Decode the errored block
+            $foundErrors = $codec->decode($tBlock, $erasures);
+
+            if ($errors > 0 && $foundErrors === null) {
+                $this->assertEquals($block, $tBlock, 'Decoder failed to correct errors');
+            }
+
+            $this->assertEquals($errors, $foundErrors, 'Found errors do not equal expected errors');
+
+            for ($i = 0; $i < $foundErrors; $i++) {
+                if ($errorLocations[$erasures[$i]] === 0) {
+                    $this->fail(sprintf('Decoder indicates error in location %d without error', $erasures[$i]));
+                }
+            }
+
+            $this->assertEquals($block, $tBlock, 'Decoder did not correct errors');
+        }
+    }
+}

+ 88 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Common/VersionTest.php

@@ -0,0 +1,88 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Common;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class VersionTest extends TestCase
+{
+    public static function versionProvider()
+    {
+        $array = array();
+
+        for ($i = 1; $i <= 40; $i++) {
+            $array[] = array($i, 4 * $i + 17);
+        }
+
+        return $array;
+    }
+
+    public static function decodeInformationProvider()
+    {
+        return array(
+            array(7, 0x07c94),
+            array(12, 0x0c762),
+            array(17, 0x1145d),
+            array(22, 0x168c9),
+            array(27, 0x1b08e),
+            array(32, 0x209d5),
+        );
+    }
+
+    /**
+     * @dataProvider versionProvider
+     * @param        integer $versionNumber
+     * @param        integer $dimension
+     */
+    public function testVersionForNumber($versionNumber, $dimension)
+    {
+        $version = Version::getVersionForNumber($versionNumber);
+
+        $this->assertNotNull($version);
+        $this->assertEquals($versionNumber, $version->getVersionNumber());
+        $this->assertNotNull($version->getAlignmentPatternCenters());
+
+        if ($versionNumber > 1) {
+            $this->assertTrue(count($version->getAlignmentPatternCenters()) > 0);
+        }
+
+        $this->assertEquals($dimension, $version->getDimensionForVersion());
+        $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::H)));
+        $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::L)));
+        $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::M)));
+        $this->assertNotNull($version->getEcBlocksForLevel(new ErrorCorrectionLevel(ErrorCorrectionLevel::Q)));
+        $this->assertNotNull($version->buildFunctionPattern());
+    }
+
+    /**
+     * @dataProvider versionProvider
+     * @param        integer $versionNumber
+     * @param        integer $dimension
+     */
+    public function testGetProvisionalVersionForDimension($versionNumber, $dimension)
+    {
+        $this->assertEquals(
+            $versionNumber,
+            Version::getProvisionalVersionForDimension($dimension)->getVersionNumber()
+        );
+    }
+
+    /**
+     * @dataProvider decodeInformationProvider
+     * @param        integer $expectedVersion
+     * @param        integer $mask
+     */
+    public function testDecodeVersionInformation($expectedVersion, $mask)
+    {
+        $version = Version::decodeVersionInformation($mask);
+        $this->assertNotNull($version);
+        $this->assertEquals($expectedVersion, $version->getVersionNumber());
+    }
+}

+ 468 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/EncoderTest.php

@@ -0,0 +1,468 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\BitArray;
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Common\Mode;
+use BaconQrCode\Common\Version;
+use PHPUnit_Framework_TestCase as TestCase;
+use ReflectionClass;
+use ReflectionMethod;
+use SplFixedArray;
+
+class EncoderTest extends TestCase
+{
+    protected $methods = array();
+
+    public function setUp()
+    {
+        // Hack to be able to test protected methods
+        $reflection = new ReflectionClass('BaconQrCode\Encoder\Encoder');
+
+        foreach ($reflection->getMethods(ReflectionMethod::IS_STATIC) as $method) {
+            $method->setAccessible(true);
+            $this->methods[$method->getName()] = $method;
+        }
+    }
+
+    public function testGetAlphanumericCode()
+    {
+        // The first ten code points are numbers.
+        for ($i = 0; $i < 10; $i++) {
+            $this->assertEquals($i, $this->methods['getAlphanumericCode']->invoke(null, ord('0') + $i));
+        }
+
+        // The next 26 code points are capital alphabet letters.
+        for ($i = 10; $i < 36; $i++) {
+            // The first ten code points are numbers
+            $this->assertEquals($i, $this->methods['getAlphanumericCode']->invoke(null, ord('A') + $i - 10));
+        }
+
+        // Others are symbol letters.
+        $this->assertEquals(36, $this->methods['getAlphanumericCode']->invoke(null, ' '));
+        $this->assertEquals(37, $this->methods['getAlphanumericCode']->invoke(null, '$'));
+        $this->assertEquals(38, $this->methods['getAlphanumericCode']->invoke(null, '%'));
+        $this->assertEquals(39, $this->methods['getAlphanumericCode']->invoke(null, '*'));
+        $this->assertEquals(40, $this->methods['getAlphanumericCode']->invoke(null, '+'));
+        $this->assertEquals(41, $this->methods['getAlphanumericCode']->invoke(null, '-'));
+        $this->assertEquals(42, $this->methods['getAlphanumericCode']->invoke(null, '.'));
+        $this->assertEquals(43, $this->methods['getAlphanumericCode']->invoke(null, '/'));
+        $this->assertEquals(44, $this->methods['getAlphanumericCode']->invoke(null, ':'));
+
+        // Should return -1 for other letters.
+        $this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, 'a'));
+        $this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, '#'));
+        $this->assertEquals(-1, $this->methods['getAlphanumericCode']->invoke(null, "\0"));
+    }
+
+    public function testChooseMode()
+    {
+        // Numeric mode
+        $this->assertSame(Mode::NUMERIC, $this->methods['chooseMode']->invoke(null, '0')->get());
+        $this->assertSame(Mode::NUMERIC, $this->methods['chooseMode']->invoke(null, '0123456789')->get());
+
+        // Alphanumeric mode
+        $this->assertSame(Mode::ALPHANUMERIC, $this->methods['chooseMode']->invoke(null, 'A')->get());
+        $this->assertSame(Mode::ALPHANUMERIC, $this->methods['chooseMode']->invoke(null, '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:')->get());
+
+        // 8-bit byte mode
+        $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, 'a')->get());
+        $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, '#')->get());
+        $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, '')->get());
+
+        // AIUE in Hiragana in SHIFT-JIS
+        $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\x8\xa\x8\xa\x8\xa\x8\xa6")->get());
+
+        // Nihon in Kanji in SHIFT-JIS
+        $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\x9\xf\x9\x7b")->get());
+
+        // Sou-Utso-Byou in Kanji in SHIFT-JIS
+        $this->assertSame(Mode::BYTE, $this->methods['chooseMode']->invoke(null, "\xe\x4\x9\x5\x9\x61")->get());
+    }
+
+    public function testEncode()
+    {
+        $qrCode   = Encoder::encode('ABCDEF', new ErrorCorrectionLevel(ErrorCorrectionLevel::H));
+        $expected = "<<\n"
+                  . " mode: ALPHANUMERIC\n"
+                  . " ecLevel: H\n"
+                  . " version: 1\n"
+                  . " maskPattern: 0\n"
+                  . " matrix:\n"
+                  . " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 1 1 1 1 1 1 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 0 1 1 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 1 0 1 1 1 0 1 1 0 0 1 1 0 0 0 1 0 0 1\n"
+                  . " 1 0 1 1 1 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0\n"
+                  . " 0 0 1 1 0 0 1 0 1 0 0 0 1 0 1 0 1 0 1 1 0\n"
+                  . " 1 1 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 0\n"
+                  . " 0 0 1 1 0 1 1 1 1 0 0 0 1 0 1 0 1 1 1 1 0\n"
+                  . " 0 0 0 0 0 0 0 0 1 0 0 1 1 1 0 1 0 1 0 0 0\n"
+                  . " 1 1 1 1 1 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 1\n"
+                  . " 1 0 0 0 0 0 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 1 0 1 1 0 1 0 1 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 1 0 1 1 1 1 0 1 0 1 0\n"
+                  . " 1 0 1 1 1 0 1 0 1 0 0 0 1 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 1 1 0 1 1 0 1 0 0 0 1 1\n"
+                  . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 0 1\n"
+                  . ">>\n";
+
+        $this->assertEquals($expected, $qrCode->__toString());
+    }
+
+    public function testSimpleUtf8Eci()
+    {
+        $qrCode   = Encoder::encode('hello', new ErrorCorrectionLevel(ErrorCorrectionLevel::H), 'utf-8');
+        $expected = "<<\n"
+                  . " mode: BYTE\n"
+                  . " ecLevel: H\n"
+                  . " version: 1\n"
+                  . " maskPattern: 3\n"
+                  . " matrix:\n"
+                  . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 1 1 0 0 1 1 1 1 0 0 0 1 1 0 1 0 0 0 0\n"
+                  . " 0 0 1 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 0\n"
+                  . " 0 1 0 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 1 1 1\n"
+                  . " 1 1 0 0 1 0 0 1 1 0 0 1 1 1 1 0 1 0 1 1 0\n"
+                  . " 0 0 0 0 1 0 1 1 1 1 0 0 0 0 0 1 0 0 1 0 0\n"
+                  . " 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 1 1 0 1 0 1 1 0 0 1 0 0\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 0 0 0 0 1 1 0 0 0 0 0\n"
+                  . " 1 0 1 1 1 0 1 0 1 1 1 0 1 0 0 0 1 1 0 0 0\n"
+                  . " 1 0 1 1 1 0 1 0 1 1 0 0 0 1 0 0 1 0 0 0 0\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 1 1 0 1 0 1 0 1 1 0\n"
+                  . " 1 1 1 1 1 1 1 0 0 1 0 1 1 1 0 1 1 0 0 0 0\n"
+                  . ">>\n";
+
+        $this->assertEquals($expected, $qrCode->__toString());
+    }
+
+    public function testAppendModeInfo()
+    {
+        $bits = new BitArray();
+        $this->methods['appendModeInfo']->invoke(null, new Mode(Mode::NUMERIC), $bits);
+        $this->assertEquals(' ...X', $bits->__toString());
+    }
+
+    public function testAppendLengthInfo()
+    {
+        // 1 letter (1/1), 10 bits.
+        $bits = new BitArray();
+        $this->methods['appendLengthInfo']->invoke(
+            null,
+            1,
+            Version::getVersionForNumber(1),
+            new Mode(Mode::NUMERIC),
+            $bits
+        );
+        $this->assertEquals(' ........ .X', $bits->__toString());
+
+        // 2 letters (2/1), 11 bits.
+        $bits = new BitArray();
+        $this->methods['appendLengthInfo']->invoke(
+            null,
+            2,
+            Version::getVersionForNumber(10),
+            new Mode(Mode::ALPHANUMERIC),
+            $bits
+        );
+        $this->assertEquals(' ........ .X.', $bits->__toString());
+
+        // 255 letters (255/1), 16 bits.
+        $bits = new BitArray();
+        $this->methods['appendLengthInfo']->invoke(
+            null,
+            255,
+            Version::getVersionForNumber(27),
+            new Mode(Mode::BYTE),
+            $bits
+        );
+        $this->assertEquals(' ........ XXXXXXXX', $bits->__toString());
+
+        // 512 letters (1024/2), 12 bits.
+        $bits = new BitArray();
+        $this->methods['appendLengthInfo']->invoke(
+            null,
+            512,
+            Version::getVersionForNumber(40),
+            new Mode(Mode::KANJI),
+            $bits
+        );
+        $this->assertEquals(' ..X..... ....', $bits->__toString());
+    }
+
+    public function testAppendBytes()
+    {
+        // Should use appendNumericBytes.
+        // 1 = 01 = 0001 in 4 bits.
+        $bits = new BitArray();
+        $this->methods['appendBytes']->invoke(
+            null,
+            '1',
+            new Mode(Mode::NUMERIC),
+            $bits,
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->assertEquals(' ...X', $bits->__toString());
+
+        // Should use appendAlphaNumericBytes.
+        // A = 10 = 0xa = 001010 in 6 bits.
+        $bits = new BitArray();
+        $this->methods['appendBytes']->invoke(
+            null,
+            'A',
+            new Mode(Mode::ALPHANUMERIC),
+            $bits,
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->assertEquals(' ..X.X.', $bits->__toString());
+
+        // Should use append8BitBytes.
+        // 0x61, 0x62, 0x63
+        $bits = new BitArray();
+        $this->methods['appendBytes']->invoke(
+            null,
+            'abc',
+            new Mode(Mode::BYTE),
+            $bits,
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->assertEquals(' .XX....X .XX...X. .XX...XX', $bits->__toString());
+
+        // Should use appendKanjiBytes.
+        // 0x93, 0x5f
+        $bits = new BitArray();
+        $this->methods['appendBytes']->invoke(
+            null,
+            "\x93\x5f",
+            new Mode(Mode::KANJI),
+            $bits,
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->assertEquals(' .XX.XX.. XXXXX', $bits->__toString());
+
+        // Lower letters such as 'a' cannot be encoded in alphanumeric mode.
+        $this->setExpectedException(
+            'BaconQrCode\Exception\WriterException',
+            'Invalid alphanumeric code'
+        );
+        $this->methods['appendBytes']->invoke(
+            null,
+            "a",
+            new Mode(Mode::ALPHANUMERIC),
+            $bits,
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+    }
+
+    public function testTerminateBits()
+    {
+        $bits = new BitArray();
+        $this->methods['terminateBits']->invoke(null, 0, $bits);
+        $this->assertEquals('', $bits->__toString());
+
+        $bits = new BitArray();
+        $this->methods['terminateBits']->invoke(null, 1, $bits);
+        $this->assertEquals(' ........', $bits->__toString());
+
+        $bits = new BitArray();
+        $bits->appendBits(0, 3);
+        $this->methods['terminateBits']->invoke(null, 1, $bits);
+        $this->assertEquals(' ........', $bits->__toString());
+
+        $bits = new BitArray();
+        $bits->appendBits(0, 5);
+        $this->methods['terminateBits']->invoke(null, 1, $bits);
+        $this->assertEquals(' ........', $bits->__toString());
+
+        $bits = new BitArray();
+        $bits->appendBits(0, 8);
+        $this->methods['terminateBits']->invoke(null, 1, $bits);
+        $this->assertEquals(' ........', $bits->__toString());
+
+        $bits = new BitArray();
+        $this->methods['terminateBits']->invoke(null, 2, $bits);
+        $this->assertEquals(' ........ XXX.XX..', $bits->__toString());
+
+        $bits = new BitArray();
+        $bits->appendBits(0, 1);
+        $this->methods['terminateBits']->invoke(null, 3, $bits);
+        $this->assertEquals(' ........ XXX.XX.. ...X...X', $bits->__toString());
+    }
+
+    public function testGetNumDataBytesAndNumEcBytesForBlockId()
+    {
+        // Version 1-H.
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 26, 9, 1, 0);
+        $this->assertEquals(9, $numDataBytes);
+        $this->assertEquals(17, $numEcBytes);
+
+        // Version 3-H.  2 blocks.
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 70, 26, 2, 0);
+        $this->assertEquals(13, $numDataBytes);
+        $this->assertEquals(22, $numEcBytes);
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 70, 26, 2, 1);
+        $this->assertEquals(13, $numDataBytes);
+        $this->assertEquals(22, $numEcBytes);
+
+        // Version 7-H. (4 + 1) blocks.
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 196, 66, 5, 0);
+        $this->assertEquals(13, $numDataBytes);
+        $this->assertEquals(26, $numEcBytes);
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 196, 66, 5, 4);
+        $this->assertEquals(14, $numDataBytes);
+        $this->assertEquals(26, $numEcBytes);
+
+        // Version 40-H. (20 + 61) blocks.
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 0);
+        $this->assertEquals(15, $numDataBytes);
+        $this->assertEquals(30, $numEcBytes);
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 20);
+        $this->assertEquals(16, $numDataBytes);
+        $this->assertEquals(30, $numEcBytes);
+        list($numDataBytes, $numEcBytes) = $this->methods['getNumDataBytesAndNumEcBytesForBlockId']->invoke(null, 3706, 1276, 81, 80);
+        $this->assertEquals(16, $numDataBytes);
+        $this->assertEquals(30, $numEcBytes);
+    }
+
+    public function testInterleaveWithEcBytes()
+    {
+        $dataBytes = SplFixedArray::fromArray(array(32, 65, 205, 69, 41, 220, 46, 128, 236), false);
+        $in        = new BitArray();
+
+        foreach ($dataBytes as $dataByte) {
+            $in->appendBits($dataByte, 8);
+        }
+
+        $outBits  = $this->methods['interleaveWithEcBytes']->invoke(null, $in, 26, 9, 1);
+        $expected = SplFixedArray::fromArray(array(
+            // Data bytes.
+            32, 65, 205, 69, 41, 220, 46, 128, 236,
+            // Error correction bytes.
+            42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61,
+        ), false);
+
+        $out = $outBits->toBytes(0, count($expected));
+
+        $this->assertEquals($expected, $out);
+    }
+
+    public function testAppendNumericBytes()
+    {
+        // 1 = 01 = 0001 in 4 bits.
+        $bits = new BitArray();
+        $this->methods['appendNumericBytes']->invoke(null, '1', $bits);
+        $this->assertEquals(' ...X', $bits->__toString());
+
+        // 12 = 0xc = 0001100 in 7 bits.
+        $bits = new BitArray();
+        $this->methods['appendNumericBytes']->invoke(null, '12', $bits);
+        $this->assertEquals(' ...XX..', $bits->__toString());
+
+        // 123 = 0x7b = 0001111011 in 10 bits.
+        $bits = new BitArray();
+        $this->methods['appendNumericBytes']->invoke(null, '123', $bits);
+        $this->assertEquals(' ...XXXX. XX', $bits->__toString());
+
+        // 1234 = "123" + "4" = 0001111011 + 0100 in 14 bits.
+        $bits = new BitArray();
+        $this->methods['appendNumericBytes']->invoke(null, '1234', $bits);
+        $this->assertEquals(' ...XXXX. XX.X..', $bits->__toString());
+
+        // Empty
+        $bits = new BitArray();
+        $this->methods['appendNumericBytes']->invoke(null, '', $bits);
+        $this->assertEquals('', $bits->__toString());
+    }
+
+    public function testAppendAlphanumericBytes()
+    {
+        $bits = new BitArray();
+        $this->methods['appendAlphanumericBytes']->invoke(null, 'A', $bits);
+        $this->assertEquals(' ..X.X.', $bits->__toString());
+
+        $bits = new BitArray();
+        $this->methods['appendAlphanumericBytes']->invoke(null, 'AB', $bits);
+        $this->assertEquals(' ..XXX..X X.X', $bits->__toString());
+
+        $bits = new BitArray();
+        $this->methods['appendAlphanumericBytes']->invoke(null, 'ABC', $bits);
+        $this->assertEquals(' ..XXX..X X.X..XX. .', $bits->__toString());
+
+        // Empty
+        $bits = new BitArray();
+        $this->methods['appendAlphanumericBytes']->invoke(null, '', $bits);
+        $this->assertEquals('', $bits->__toString());
+
+        // Invalid data
+        $this->setExpectedException('BaconQrCode\Exception\WriterException', 'Invalid alphanumeric code');
+        $bits = new BitArray();
+        $this->methods['appendAlphanumericBytes']->invoke(null, 'abc', $bits);
+    }
+
+    public function testAppend8BitBytes()
+    {
+        // 0x61, 0x62, 0x63
+        $bits = new BitArray();
+        $this->methods['append8BitBytes']->invoke(null, 'abc', $bits, Encoder::DEFAULT_BYTE_MODE_ECODING);
+        $this->assertEquals(' .XX....X .XX...X. .XX...XX', $bits->__toString());
+
+        // Empty
+        $bits = new BitArray();
+        $this->methods['append8BitBytes']->invoke(null, '', $bits, Encoder::DEFAULT_BYTE_MODE_ECODING);
+        $this->assertEquals('', $bits->__toString());
+    }
+
+    public function testAppendKanjiBytes()
+    {
+        // Numbers are from page 21 of JISX0510:2004
+        $bits = new BitArray();
+        $this->methods['appendKanjiBytes']->invoke(null, "\x93\x5f", $bits);
+        $this->assertEquals(' .XX.XX.. XXXXX', $bits->__toString());
+
+        $this->methods['appendKanjiBytes']->invoke(null, "\xe4\xaa", $bits);
+        $this->assertEquals(' .XX.XX.. XXXXXXX. X.X.X.X. X.', $bits->__toString());
+    }
+
+    public function testGenerateEcBytes()
+    {
+        // Numbers are from http://www.swetake.com/qr/qr3.html and
+        // http://www.swetake.com/qr/qr9.html
+        $dataBytes = SplFixedArray::fromArray(array(32, 65, 205, 69, 41, 220, 46, 128, 236), false);
+        $ecBytes   = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 17);
+        $expected  = SplFixedArray::fromArray(array(42, 159, 74, 221, 244, 169, 239, 150, 138, 70, 237, 85, 224, 96, 74, 219, 61), false);
+        $this->assertEquals($expected, $ecBytes);
+
+        $dataBytes = SplFixedArray::fromArray(array(67, 70, 22, 38, 54, 70, 86, 102, 118, 134, 150, 166, 182, 198, 214), false);
+        $ecBytes   = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 18);
+        $expected  = SplFixedArray::fromArray(array(175, 80, 155, 64, 178, 45, 214, 233, 65, 209, 12, 155, 117, 31, 140, 214, 27, 187), false);
+        $this->assertEquals($expected, $ecBytes);
+
+        // High-order zero coefficient case.
+        $dataBytes = SplFixedArray::fromArray(array(32, 49, 205, 69, 42, 20, 0, 236, 17), false);
+        $ecBytes   = $this->methods['generateEcBytes']->invoke(null, $dataBytes, 17);
+        $expected  = SplFixedArray::fromArray(array(0, 3, 130, 179, 194, 0, 55, 211, 110, 79, 98, 72, 170, 96, 211, 137, 213), false);
+        $this->assertEquals($expected, $ecBytes);
+    }
+}

+ 281 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/MaskUtilTest.php

@@ -0,0 +1,281 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use PHPUnit_Framework_TestCase as TestCase;
+
+class MaskUtilTest extends TestCase
+{
+    public static function dataMaskBitProvider()
+    {
+        return array(
+            array(
+                0,
+                array(
+                    array(1, 0, 1, 0, 1, 0),
+                    array(0, 1, 0, 1, 0, 1),
+                    array(1, 0, 1, 0, 1, 0),
+                    array(0, 1, 0, 1, 0, 1),
+                    array(1, 0, 1, 0, 1, 0),
+                    array(0, 1, 0, 1, 0, 1),
+                )
+            ),
+            array(
+                1,
+                array(
+                    array(1, 1, 1, 1, 1, 1),
+                    array(0, 0, 0, 0, 0, 0),
+                    array(1, 1, 1, 1, 1, 1),
+                    array(0, 0, 0, 0, 0, 0),
+                    array(1, 1, 1, 1, 1, 1),
+                    array(0, 0, 0, 0, 0, 0),
+                )
+            ),
+            array(
+                2,
+                array(
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                )
+            ),
+            array(
+                3,
+                array(
+                    array(1, 0, 0, 1, 0, 0),
+                    array(0, 0, 1, 0, 0, 1),
+                    array(0, 1, 0, 0, 1, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(0, 0, 1, 0, 0, 1),
+                    array(0, 1, 0, 0, 1, 0),
+                )
+            ),
+            array(
+                4,
+                array(
+                    array(1, 1, 1, 0, 0, 0),
+                    array(1, 1, 1, 0, 0, 0),
+                    array(0, 0, 0, 1, 1, 1),
+                    array(0, 0, 0, 1, 1, 1),
+                    array(1, 1, 1, 0, 0, 0),
+                    array(1, 1, 1, 0, 0, 0),
+                )
+            ),
+            array(
+                5,
+                array(
+                    array(1, 1, 1, 1, 1, 1),
+                    array(1, 0, 0, 0, 0, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 1, 0, 1, 0),
+                    array(1, 0, 0, 1, 0, 0),
+                    array(1, 0, 0, 0, 0, 0),
+                )
+            ),
+            array(
+                6,
+                array(
+                    array(1, 1, 1, 1, 1, 1),
+                    array(1, 1, 1, 0, 0, 0),
+                    array(1, 1, 0, 1, 1, 0),
+                    array(1, 0, 1, 0, 1, 0),
+                    array(1, 0, 1, 1, 0, 1),
+                    array(1, 0, 0, 0, 1, 1),
+                )
+            ),
+            array(
+                7,
+                array(
+                    array(1, 0, 1, 0, 1, 0),
+                    array(0, 0, 0, 1, 1, 1),
+                    array(1, 0, 0, 0, 1, 1),
+                    array(0, 1, 0, 1, 0, 1),
+                    array(1, 1, 1, 0, 0, 0),
+                    array(0, 1, 1, 1, 0, 0),
+                )
+            ),
+        );
+    }
+
+    /**
+     * @dataProvider dataMaskBitProvider
+     * @param        integer $maskPattern
+     * @param        array   $expected
+     * @return       void
+     */
+    public function testGetDatMaskBit($maskPattern, array $expected)
+    {
+        for ($x = 0; $x < 6; $x++) {
+            for ($y = 0; $y < 6; $y++) {
+                if (($expected[$y][$x] === 1) !== MaskUtil::getDataMaskBit($maskPattern, $x, $y)) {
+                    $this->fail('Data mask bit did not match');
+                }
+            }
+        }
+    }
+
+    public function testApplyMaskPenaltyRule1()
+    {
+        $matrix = new ByteMatrix(4, 1);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 0);
+        $matrix->set(2, 0, 0);
+        $matrix->set(3, 0, 0);
+
+        $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule1($matrix));
+
+        // Horizontal
+        $matrix = new ByteMatrix(6, 1);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 0);
+        $matrix->set(2, 0, 0);
+        $matrix->set(3, 0, 0);
+        $matrix->set(4, 0, 0);
+        $matrix->set(5, 0, 1);
+        $this->assertEquals(3, MaskUtil::applyMaskPenaltyRule1($matrix));
+        $matrix->set(5, 0, 0);
+        $this->assertEquals(4, MaskUtil::applyMaskPenaltyRule1($matrix));
+
+        // Vertical
+        $matrix = new ByteMatrix(1, 6);
+        $matrix->set(0, 0, 0);
+        $matrix->set(0, 1, 0);
+        $matrix->set(0, 2, 0);
+        $matrix->set(0, 3, 0);
+        $matrix->set(0, 4, 0);
+        $matrix->set(0, 5, 1);
+        $this->assertEquals(3, MaskUtil::applyMaskPenaltyRule1($matrix));
+        $matrix->set(0, 5, 0);
+        $this->assertEquals(4, MaskUtil::applyMaskPenaltyRule1($matrix));
+    }
+
+    public function testApplyMaskPenaltyRule2()
+    {
+        $matrix = new ByteMatrix(1, 1);
+        $matrix->set(0, 0, 0);
+        $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule2($matrix));
+
+        $matrix = new ByteMatrix(2, 2);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 0);
+        $matrix->set(0, 1, 0);
+        $matrix->set(1, 1, 1);
+        $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule2($matrix));
+
+        $matrix = new ByteMatrix(2, 2);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 0);
+        $matrix->set(0, 1, 0);
+        $matrix->set(1, 1, 0);
+        $this->assertEquals(3, MaskUtil::applyMaskPenaltyRule2($matrix));
+
+        $matrix = new ByteMatrix(3, 3);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 0);
+        $matrix->set(2, 0, 0);
+        $matrix->set(0, 1, 0);
+        $matrix->set(1, 1, 0);
+        $matrix->set(2, 1, 0);
+        $matrix->set(0, 2, 0);
+        $matrix->set(1, 2, 0);
+        $matrix->set(2, 2, 0);
+        $this->assertEquals(3 * 4, MaskUtil::applyMaskPenaltyRule2($matrix));
+    }
+
+    public function testApplyMaskPenalty3()
+    {
+        // Horizontal 00001011101
+        $matrix = new ByteMatrix(11, 1);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 0);
+        $matrix->set(2, 0, 0);
+        $matrix->set(3, 0, 0);
+        $matrix->set(4, 0, 1);
+        $matrix->set(5, 0, 0);
+        $matrix->set(6, 0, 1);
+        $matrix->set(7, 0, 1);
+        $matrix->set(8, 0, 1);
+        $matrix->set(9, 0, 0);
+        $matrix->set(10, 0, 1);
+        $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
+
+        // Horizontal 10111010000
+        $matrix = new ByteMatrix(11, 1);
+        $matrix->set(0, 0, 1);
+        $matrix->set(1, 0, 0);
+        $matrix->set(2, 0, 1);
+        $matrix->set(3, 0, 1);
+        $matrix->set(4, 0, 1);
+        $matrix->set(5, 0, 0);
+        $matrix->set(6, 0, 1);
+        $matrix->set(7, 0, 0);
+        $matrix->set(8, 0, 0);
+        $matrix->set(9, 0, 0);
+        $matrix->set(10, 0, 0);
+        $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
+
+        // Vertical 00001011101
+        $matrix = new ByteMatrix(1, 11);
+        $matrix->set(0, 0, 0);
+        $matrix->set(0, 1, 0);
+        $matrix->set(0, 2, 0);
+        $matrix->set(0, 3, 0);
+        $matrix->set(0, 4, 1);
+        $matrix->set(0, 5, 0);
+        $matrix->set(0, 6, 1);
+        $matrix->set(0, 7, 1);
+        $matrix->set(0, 8, 1);
+        $matrix->set(0, 9, 0);
+        $matrix->set(0, 10, 1);
+        $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
+
+        // Vertical 10111010000
+        $matrix = new ByteMatrix(1, 11);
+        $matrix->set(0, 0, 1);
+        $matrix->set(0, 1, 0);
+        $matrix->set(0, 2, 1);
+        $matrix->set(0, 3, 1);
+        $matrix->set(0, 4, 1);
+        $matrix->set(0, 5, 0);
+        $matrix->set(0, 6, 1);
+        $matrix->set(0, 7, 0);
+        $matrix->set(0, 8, 0);
+        $matrix->set(0, 9, 0);
+        $matrix->set(0, 10, 0);
+        $this->assertEquals(40, MaskUtil::applyMaskPenaltyRule3($matrix));
+    }
+
+    public function testApplyMaskPenaltyRule4()
+    {
+        // Dark cell ratio = 0%
+        $matrix = new ByteMatrix(1, 1);
+        $matrix->set(0, 0, 0);
+        $this->assertEquals(100, MaskUtil::applyMaskPenaltyRule4($matrix));
+
+        // Dark cell ratio = 5%
+        $matrix = new ByteMatrix(2, 1);
+        $matrix->set(0, 0, 0);
+        $matrix->set(0, 0, 1);
+        $this->assertEquals(0, MaskUtil::applyMaskPenaltyRule4($matrix));
+
+        // Dark cell ratio = 66.67%
+        $matrix = new ByteMatrix(6, 1);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 1);
+        $matrix->set(2, 0, 1);
+        $matrix->set(3, 0, 1);
+        $matrix->set(4, 0, 1);
+        $matrix->set(5, 0, 0);
+        $this->assertEquals(30, MaskUtil::applyMaskPenaltyRule4($matrix));
+    }
+}

+ 336 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Encoder/MatrixUtilTest.php

@@ -0,0 +1,336 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\BitArray;
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Common\Version;
+use PHPUnit_Framework_TestCase as TestCase;
+use ReflectionClass;
+use ReflectionMethod;
+
+class MatrixUtilTest extends TestCase
+{
+    protected $methods = array();
+
+    public function setUp()
+    {
+        // Hack to be able to test protected methods
+        $reflection = new ReflectionClass('BaconQrCode\Encoder\MatrixUtil');
+
+        foreach ($reflection->getMethods(ReflectionMethod::IS_STATIC) as $method) {
+            $method->setAccessible(true);
+            $this->methods[$method->getName()] = $method;
+        }
+    }
+
+    public function testToString()
+    {
+        $matrix= new ByteMatrix(3, 3);
+        $matrix->set(0, 0, 0);
+        $matrix->set(1, 0, 1);
+        $matrix->set(2, 0, 0);
+        $matrix->set(0, 1, 1);
+        $matrix->set(1, 1, 0);
+        $matrix->set(2, 1, 1);
+        $matrix->set(0, 2, -1);
+        $matrix->set(1, 2, -1);
+        $matrix->set(2, 2, -1);
+
+        $expected = " 0 1 0\n 1 0 1\n      \n";
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testClearMatrix()
+    {
+        $matrix = new ByteMatrix(2, 2);
+        MatrixUtil::clearMatrix($matrix);
+
+        $this->assertEquals(-1, $matrix->get(0, 0));
+        $this->assertEquals(-1, $matrix->get(1, 0));
+        $this->assertEquals(-1, $matrix->get(0, 1));
+        $this->assertEquals(-1, $matrix->get(1, 1));
+    }
+
+    public function testEmbedBasicPatterns1()
+    {
+        $matrix = new ByteMatrix(21, 21);
+        MatrixUtil::clearMatrix($matrix);
+        $this->methods['embedBasicPatterns']->invoke(
+            null,
+            Version::getVersionForNumber(1),
+            $matrix
+        );
+        $expected = " 1 1 1 1 1 1 1 0           0 1 1 1 1 1 1 1\n"
+                  . " 1 0 0 0 0 0 1 0           0 1 0 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0           0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0           0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0           0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0           0 1 0 0 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0           0 0 0 0 0 0 0 0\n"
+                  . "             1                            \n"
+                  . "             0                            \n"
+                  . "             1                            \n"
+                  . "             0                            \n"
+                  . "             1                            \n"
+                  . " 0 0 0 0 0 0 0 0 1                        \n"
+                  . " 1 1 1 1 1 1 1 0                          \n"
+                  . " 1 0 0 0 0 0 1 0                          \n"
+                  . " 1 0 1 1 1 0 1 0                          \n"
+                  . " 1 0 1 1 1 0 1 0                          \n"
+                  . " 1 0 1 1 1 0 1 0                          \n"
+                  . " 1 0 0 0 0 0 1 0                          \n"
+                  . " 1 1 1 1 1 1 1 0                          \n";
+
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testEmbedBasicPatterns2()
+    {
+        $matrix = new ByteMatrix(25, 25);
+        MatrixUtil::clearMatrix($matrix);
+        $this->methods['embedBasicPatterns']->invoke(
+            null,
+            Version::getVersionForNumber(2),
+            $matrix
+        );
+        $expected = " 1 1 1 1 1 1 1 0                   0 1 1 1 1 1 1 1\n"
+                  . " 1 0 0 0 0 0 1 0                   0 1 0 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0                   0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0                   0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0                   0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0                   0 1 0 0 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0                   0 0 0 0 0 0 0 0\n"
+                  . "             1                                    \n"
+                  . "             0                                    \n"
+                  . "             1                                    \n"
+                  . "             0                                    \n"
+                  . "             1                                    \n"
+                  . "             0                                    \n"
+                  . "             1                                    \n"
+                  . "             0                                    \n"
+                  . "             1                   1 1 1 1 1        \n"
+                  . " 0 0 0 0 0 0 0 0 1               1 0 0 0 1        \n"
+                  . " 1 1 1 1 1 1 1 0                 1 0 1 0 1        \n"
+                  . " 1 0 0 0 0 0 1 0                 1 0 0 0 1        \n"
+                  . " 1 0 1 1 1 0 1 0                 1 1 1 1 1        \n"
+                  . " 1 0 1 1 1 0 1 0                                  \n"
+                  . " 1 0 1 1 1 0 1 0                                  \n"
+                  . " 1 0 0 0 0 0 1 0                                  \n"
+                  . " 1 1 1 1 1 1 1 0                                  \n";
+
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testEmbedTypeInfo()
+    {
+        $matrix = new ByteMatrix(21, 21);
+        MatrixUtil::clearMatrix($matrix);
+        $this->methods['embedTypeInfo']->invoke(
+            null,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::M),
+            5,
+            $matrix
+        );
+        $expected = "                 0                        \n"
+                  . "                 1                        \n"
+                  . "                 1                        \n"
+                  . "                 1                        \n"
+                  . "                 0                        \n"
+                  . "                 0                        \n"
+                  . "                                          \n"
+                  . "                 1                        \n"
+                  . " 1 0 0 0 0 0   0 1         1 1 0 0 1 1 1 0\n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                 0                        \n"
+                  . "                 0                        \n"
+                  . "                 0                        \n"
+                  . "                 0                        \n"
+                  . "                 0                        \n"
+                  . "                 0                        \n"
+                  . "                 1                        \n";
+
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testEmbedVersionInfo()
+    {
+        $matrix = new ByteMatrix(21, 21);
+        MatrixUtil::clearMatrix($matrix);
+        $this->methods['maybeEmbedVersionInfo']->invoke(
+            null,
+            Version::getVersionForNumber(7),
+            $matrix
+        );
+        $expected = "                     0 0 1                \n"
+                  . "                     0 1 0                \n"
+                  . "                     0 1 0                \n"
+                  . "                     0 1 1                \n"
+                  . "                     1 1 1                \n"
+                  . "                     0 0 0                \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . " 0 0 0 0 1 0                              \n"
+                  . " 0 1 1 1 1 0                              \n"
+                  . " 1 0 0 1 1 0                              \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n"
+                  . "                                          \n";
+
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testEmbedDataBits()
+    {
+        $matrix = new ByteMatrix(21, 21);
+        MatrixUtil::clearMatrix($matrix);
+        $this->methods['embedBasicPatterns']->invoke(
+            null,
+            Version::getVersionForNumber(1),
+            $matrix
+        );
+
+        $bits = new BitArray();
+        $this->methods['embedDataBits']->invoke(
+            null,
+            $bits,
+            -1,
+            $matrix
+        );
+
+        $expected = " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n"
+                  . " 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n";
+
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testBuildMatrix()
+    {
+        $bytes = array(
+            32, 65, 205, 69, 41, 220, 46, 128, 236, 42, 159, 74, 221, 244, 169,
+            239, 150, 138, 70, 237, 85, 224, 96, 74, 219 , 61
+        );
+        $bits = new BitArray();
+
+        foreach ($bytes as $byte) {
+            $bits->appendBits($byte, 8);
+        }
+
+        $matrix = new ByteMatrix(21, 21);
+        MatrixUtil::buildMatrix(
+            $bits,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::H),
+            Version::getVersionForNumber(1),
+            3,
+            $matrix
+        );
+
+        $expected = " 1 1 1 1 1 1 1 0 0 1 1 0 0 0 1 1 1 1 1 1 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 0 0 1 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 1 1 1 0 1 0 1 1 0 0 1 0 1 0 1 1 1 0 1\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 1 1 1 0 1 0 0 0 0 0 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 0\n"
+                  . " 0 0 1 1 0 0 1 1 1 0 0 1 1 1 1 0 1 0 0 0 0\n"
+                  . " 1 0 1 0 1 0 0 0 0 0 1 1 1 0 0 1 0 1 1 1 0\n"
+                  . " 1 1 1 1 0 1 1 0 1 0 1 1 1 0 0 1 1 1 0 1 0\n"
+                  . " 1 0 1 0 1 1 0 1 1 1 0 0 1 1 1 0 0 1 0 1 0\n"
+                  . " 0 0 1 0 0 1 1 1 0 0 0 0 0 0 1 0 1 1 1 1 1\n"
+                  . " 0 0 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 1 0 1 1\n"
+                  . " 1 1 1 1 1 1 1 0 1 1 1 1 0 0 0 0 1 0 1 1 0\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 0 0 0\n"
+                  . " 1 0 1 1 1 0 1 0 0 1 0 0 1 1 0 0 1 0 0 1 1\n"
+                  . " 1 0 1 1 1 0 1 0 1 1 0 1 0 0 0 0 0 1 1 1 0\n"
+                  . " 1 0 1 1 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 0 0\n"
+                  . " 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0\n"
+                  . " 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 0 1 0 0 1 0\n";
+
+        $this->assertEquals($expected, $matrix->__toString());
+    }
+
+    public function testFindMsbSet()
+    {
+        $this->assertEquals(0, $this->methods['findMsbSet']->invoke(null, 0));
+        $this->assertEquals(1, $this->methods['findMsbSet']->invoke(null, 1));
+        $this->assertEquals(8, $this->methods['findMsbSet']->invoke(null, 0x80));
+        $this->assertEquals(32, $this->methods['findMsbSet']->invoke(null, 0x80000000));
+    }
+
+    public function testCalculateBchCode()
+    {
+        // Encoding of type information.
+        // From Appendix C in JISX0510:2004 (p 65)
+        $this->assertEquals(0xdc, $this->methods['calculateBchCode']->invoke(null, 5, 0x537));
+        // From http://www.swetake.com/qr/qr6.html
+        $this->assertEquals(0x1c2, $this->methods['calculateBchCode']->invoke(null, 0x13, 0x537));
+        // From http://www.swetake.com/qr/qr11.html
+        $this->assertEquals(0x214, $this->methods['calculateBchCode']->invoke(null, 0x1b, 0x537));
+
+        // Encoding of version information.
+        // From Appendix D in JISX0510:2004 (p 68)
+        $this->assertEquals(0xc94, $this->methods['calculateBchCode']->invoke(null, 7, 0x1f25));
+        $this->assertEquals(0x5bc, $this->methods['calculateBchCode']->invoke(null, 8, 0x1f25));
+        $this->assertEquals(0xa99, $this->methods['calculateBchCode']->invoke(null, 9, 0x1f25));
+        $this->assertEquals(0x4d3, $this->methods['calculateBchCode']->invoke(null, 10, 0x1f25));
+        $this->assertEquals(0x9a6, $this->methods['calculateBchCode']->invoke(null, 20, 0x1f25));
+        $this->assertEquals(0xd75, $this->methods['calculateBchCode']->invoke(null, 30, 0x1f25));
+        $this->assertEquals(0xc69, $this->methods['calculateBchCode']->invoke(null, 40, 0x1f25));
+    }
+
+    public function testMakeVersionInfoBits()
+    {
+        // From Appendix D in JISX0510:2004 (p 68)
+        $bits = new BitArray();
+        $this->methods['makeVersionInfoBits']->invoke(null, Version::getVersionForNumber(7), $bits);
+        $this->assertEquals(' ...XXXXX ..X..X.X ..', $bits->__toString());
+    }
+
+    public function testMakeTypeInfoBits()
+    {
+        // From Appendix D in JISX0510:2004 (p 68)
+        $bits = new BitArray();
+        $this->methods['makeTypeInfoBits']->invoke(null, new ErrorCorrectionLevel(ErrorCorrectionLevel::M), 5, $bits);
+        $this->assertEquals(' X......X X..XXX.', $bits->__toString());
+    }
+}

+ 99 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/HtmlTest.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Renderer\Text\Html;
+use BaconQrCode\Writer;
+use PHPUnit_Framework_TestCase as TestCase;
+
+class HtmlTest extends TestCase
+{
+    /**
+     * @var Html
+     */
+    protected $renderer;
+
+    /**
+     * @var Writer
+     */
+    protected $writer;
+
+    public function setUp()
+    {
+        $this->renderer = new Html();
+        $this->writer = new Writer($this->renderer);
+    }
+
+    public function testBasicRender()
+    {
+        $content = 'foobar';
+        $expected =
+            '<pre style="font-family: monospace; line-height: 0.65em; letter-spacing: -1px" class="">' .
+            "                       \n" .
+            " ███████ █████ ███████ \n" .
+            " █     █  █ █  █     █ \n" .
+            " █ ███ █  ██   █ ███ █ \n" .
+            " █ ███ █  ███  █ ███ █ \n" .
+            " █ ███ █   █ █ █ ███ █ \n" .
+            " █     █    ██ █     █ \n" .
+            " ███████ █ █ █ ███████ \n" .
+            "         █████         \n" .
+            " ██ ██ █  ██ █ █     █ \n" .
+            "    ██    ██ █ █ ██    \n" .
+            "  ████████ █  ██ █  ██ \n" .
+            "           ██      █ █ \n" .
+            "  ██  ███  █   █  █  █ \n" .
+            "         █ ███    █ █  \n" .
+            " ███████  ██ ██████    \n" .
+            " █     █   ████   ██   \n" .
+            " █ ███ █ ██ ██ ██ █ ██ \n" .
+            " █ ███ █ ██ ██  █ ██   \n" .
+            " █ ███ █   █   █ ██ ██ \n" .
+            " █     █ ███  ███ ████ \n" .
+            " ███████ ████   ██     \n" .
+            "                       \n" .
+            '</pre>'
+        ;
+
+        $qrCode = Encoder::encode(
+            $content,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->assertEquals($expected, $this->renderer->render($qrCode));
+    }
+
+    public function testSetStyle()
+    {
+        $content = 'foobar';
+        $qrCode = Encoder::encode(
+            $content,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->renderer->setStyle('bar');
+        $this->assertEquals('bar', $this->renderer->getStyle());
+        $this->assertStringMatchesFormat('%astyle="bar"%a', $this->renderer->render($qrCode));
+    }
+
+    public function testSetClass()
+    {
+        $content = 'foobar';
+        $qrCode = Encoder::encode(
+            $content,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->renderer->setClass('bar');
+        $this->assertEquals('bar', $this->renderer->getClass());
+        $this->assertStringMatchesFormat('%aclass="bar"%a', $this->renderer->render($qrCode));
+    }
+}

+ 149 - 0
vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/TextTest.php

@@ -0,0 +1,149 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+namespace BaconQrCode\Encoder;
+
+use BaconQrCode\Common\ErrorCorrectionLevel;
+use BaconQrCode\Renderer\Text\Plain;
+use BaconQrCode\Writer;
+use PHPUnit_Framework_TestCase as TestCase;
+
+class PlainTest extends TestCase
+{
+    /**
+     * @var Plain
+     */
+    protected $renderer;
+
+    /**
+     * @var Writer
+     */
+    protected $writer;
+
+    public function setUp()
+    {
+        $this->renderer = new Plain();
+        $this->writer = new Writer($this->renderer);
+    }
+
+    public function testBasicRender()
+    {
+        $content = 'foobar';
+        $expected =
+            "                       \n" .
+            " ███████ █████ ███████ \n" .
+            " █     █  █ █  █     █ \n" .
+            " █ ███ █  ██   █ ███ █ \n" .
+            " █ ███ █  ███  █ ███ █ \n" .
+            " █ ███ █   █ █ █ ███ █ \n" .
+            " █     █    ██ █     █ \n" .
+            " ███████ █ █ █ ███████ \n" .
+            "         █████         \n" .
+            " ██ ██ █  ██ █ █     █ \n" .
+            "    ██    ██ █ █ ██    \n" .
+            "  ████████ █  ██ █  ██ \n" .
+            "           ██      █ █ \n" .
+            "  ██  ███  █   █  █  █ \n" .
+            "         █ ███    █ █  \n" .
+            " ███████  ██ ██████    \n" .
+            " █     █   ████   ██   \n" .
+            " █ ███ █ ██ ██ ██ █ ██ \n" .
+            " █ ███ █ ██ ██  █ ██   \n" .
+            " █ ███ █   █   █ ██ ██ \n" .
+            " █     █ ███  ███ ████ \n" .
+            " ███████ ████   ██     \n" .
+            "                       \n"
+        ;
+
+        $qrCode = Encoder::encode(
+            $content,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->assertEquals($expected, $this->renderer->render($qrCode));
+    }
+
+    public function testBasicRenderNoMargins()
+    {
+        $content = 'foobar';
+        $expected =
+            "███████ █████ ███████\n" .
+            "█     █  █ █  █     █\n" .
+            "█ ███ █  ██   █ ███ █\n" .
+            "█ ███ █  ███  █ ███ █\n" .
+            "█ ███ █   █ █ █ ███ █\n" .
+            "█     █    ██ █     █\n" .
+            "███████ █ █ █ ███████\n" .
+            "        █████        \n" .
+            "██ ██ █  ██ █ █     █\n" .
+            "   ██    ██ █ █ ██   \n" .
+            " ████████ █  ██ █  ██\n" .
+            "          ██      █ █\n" .
+            " ██  ███  █   █  █  █\n" .
+            "        █ ███    █ █ \n" .
+            "███████  ██ ██████   \n" .
+            "█     █   ████   ██  \n" .
+            "█ ███ █ ██ ██ ██ █ ██\n" .
+            "█ ███ █ ██ ██  █ ██  \n" .
+            "█ ███ █   █   █ ██ ██\n" .
+            "█     █ ███  ███ ████\n" .
+            "███████ ████   ██    \n"
+        ;
+
+        $qrCode = Encoder::encode(
+            $content,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->renderer->setMargin(0);
+        $this->assertEquals(0, $this->renderer->getMargin());
+        $this->assertEquals($expected, $this->renderer->render($qrCode));
+    }
+
+    public function testBasicRenderCustomChar()
+    {
+        $content = 'foobar';
+        $expected =
+            "-----------------------\n" .
+            "-#######-#####-#######-\n" .
+            "-#-----#--#-#--#-----#-\n" .
+            "-#-###-#--##---#-###-#-\n" .
+            "-#-###-#--###--#-###-#-\n" .
+            "-#-###-#---#-#-#-###-#-\n" .
+            "-#-----#----##-#-----#-\n" .
+            "-#######-#-#-#-#######-\n" .
+            "---------#####---------\n" .
+            "-##-##-#--##-#-#-----#-\n" .
+            "----##----##-#-#-##----\n" .
+            "--########-#--##-#--##-\n" .
+            "-----------##------#-#-\n" .
+            "--##--###--#---#--#--#-\n" .
+            "---------#-###----#-#--\n" .
+            "-#######--##-######----\n" .
+            "-#-----#---####---##---\n" .
+            "-#-###-#-##-##-##-#-##-\n" .
+            "-#-###-#-##-##--#-##---\n" .
+            "-#-###-#---#---#-##-##-\n" .
+            "-#-----#-###--###-####-\n" .
+            "-#######-####---##-----\n" .
+            "-----------------------\n"
+        ;
+
+        $qrCode = Encoder::encode(
+            $content,
+            new ErrorCorrectionLevel(ErrorCorrectionLevel::L),
+            Encoder::DEFAULT_BYTE_MODE_ECODING
+        );
+        $this->renderer->setFullBlock('#');
+        $this->renderer->setEmptyBlock('-');
+        $this->assertEquals('#', $this->renderer->getFullBlock());
+        $this->assertEquals('-', $this->renderer->getEmptyBlock());
+        $this->assertEquals($expected, $this->renderer->render($qrCode));
+    }
+}

+ 10 - 0
vendor/bacon/bacon-qr-code/tests/bootstrap.php

@@ -0,0 +1,10 @@
+<?php
+/**
+ * BaconQrCode
+ *
+ * @link      http://github.com/Bacon/BaconQrCode For the canonical source repository
+ * @copyright 2013 Ben 'DASPRiD' Scholzen
+ * @license   http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
+ */
+
+require_once __DIR__ . '/../autoload_register.php';

+ 11 - 0
vendor/bacon/bacon-qr-code/tests/phpunit.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phpunit bootstrap="./bootstrap.php" colors="true">
+    <testsuite name="BaconQrCode">
+        <directory>.</directory>
+    </testsuite>
+    <filter>
+        <whitelist>
+            <directory suffix=".php">../src/</directory>
+        </whitelist>
+    </filter>
+</phpunit>

+ 23 - 0
vendor/bin/carbon

@@ -0,0 +1,23 @@
+#!/usr/bin/env php
+<?php
+
+use Carbon\Cli\Invoker;
+
+$dir = __DIR__.'/..';
+
+if (!file_exists($dir.'/autoload.php')) {
+    $dir = __DIR__.'/../vendor';
+}
+
+if (!file_exists($dir.'/autoload.php')) {
+    $dir = __DIR__.'/../../..';
+}
+
+if (!file_exists($dir.'/autoload.php')) {
+    echo 'Autoload not found.';
+    exit(1);
+}
+
+require $dir.'/autoload.php';
+
+exit((new Invoker())(...$argv) ? 0 : 1);

+ 4 - 0
vendor/bin/doctrine-dbal

@@ -0,0 +1,4 @@
+#!/usr/bin/env php
+<?php
+
+require __DIR__ . '/doctrine-dbal.php';

+ 98 - 0
vendor/bin/patch-type-declarations

@@ -0,0 +1,98 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if ('cli' !== \PHP_SAPI) {
+    throw new Exception('This script must be run from the command line.');
+}
+
+if (\in_array('-h', $argv) || \in_array('--help', $argv)) {
+    echo implode(PHP_EOL, [
+        ' Patches type declarations based on "@return" PHPDoc and triggers deprecations for',
+        ' incompatible method declarations.',
+        '',
+        ' This assists you to make your package compatible with Symfony 6, but it can be used',
+        ' for any class/package.',
+        '',
+        ' Available configuration via environment variables:',
+        '  SYMFONY_PATCH_TYPE_DECLARATIONS',
+        '      An url-encoded string to change the behavior of the script. Available parameters:',
+        '      - "force": any value enables deprecation notices - can be any of:',
+        '          - "phpdoc" to patch only docblock annotations',
+        '          - "2" to add all possible return types',
+        '          - "1" to add return types but only to tests/final/internal/private methods',
+        '      - "php": the target version of PHP - e.g. "7.1" doesn\'t generate "object" types',
+        '      - "deprecations": "1" to trigger a deprecation notice when a child class misses a',
+        '                        return type while the parent declares an "@return" annotation',
+        '',
+        '  SYMFONY_PATCH_TYPE_EXCLUDE',
+        '      A regex matched against the full path to the class - any match will be excluded',
+        '',
+        ' Example: "SYMFONY_PATCH_TYPE_DECLARATIONS=php=7.4 ./patch-type-declarations"',
+    ]);
+    exit;
+}
+
+if (false === getenv('SYMFONY_PATCH_TYPE_DECLARATIONS')) {
+    putenv('SYMFONY_PATCH_TYPE_DECLARATIONS=force=2');
+    echo 'No SYMFONY_PATCH_TYPE_DECLARATIONS env var set, patching type declarations in all methods (run the command with "-h" for more information).'.PHP_EOL;
+}
+
+if (is_file($autoload = __DIR__.'/../../../../autoload.php')) {
+    // noop
+} elseif (is_file($autoload = __DIR__.'/../../../../../../../autoload.php')) {
+    // noop
+} else {
+    echo PHP_EOL.'  /!\ Cannot find the Composer autoloader, did you forget to run "composer install"?'.PHP_EOL;
+    exit(1);
+}
+
+if (is_file($phpunitAutoload = dirname($autoload).'/bin/.phpunit/phpunit/vendor/autoload.php')) {
+    require $phpunitAutoload;
+}
+
+$loader = require $autoload;
+
+Symfony\Component\ErrorHandler\DebugClassLoader::enable();
+
+$deprecations = [];
+set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations) {
+    if (\E_USER_DEPRECATED !== $type) {
+        return;
+    }
+
+    [,,,,, $class,] = explode('"', $msg);
+    $deprecations[$class][] = $msg;
+});
+
+$exclude = getenv('SYMFONY_PATCH_TYPE_EXCLUDE') ?: null;
+foreach ($loader->getClassMap() as $class => $file) {
+    if (false !== strpos($file = realpath($file), \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR)) {
+        continue;
+    }
+
+    if ($exclude && preg_match($exclude, $file)) {
+        continue;
+    }
+
+    class_exists($class);
+}
+
+Symfony\Component\ErrorHandler\DebugClassLoader::checkClasses();
+
+foreach ($deprecations as $class => $classDeprecations) {
+    echo $class.' ('.\count($classDeprecations).')'.PHP_EOL;
+    echo implode(PHP_EOL, $classDeprecations).PHP_EOL.PHP_EOL;
+}
+
+if ($deprecations && false !== strpos(getenv('SYMFONY_PATCH_TYPE_DECLARATIONS') ?? '', 'force')) {
+    echo 'These deprecations might be fixed by the patch script, run this again to check for type deprecations.'.PHP_EOL;
+}

+ 205 - 0
vendor/bin/php-parse

@@ -0,0 +1,205 @@
+#!/usr/bin/env php
+<?php
+
+foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
+    if (file_exists($file)) {
+        require $file;
+        break;
+    }
+}
+
+ini_set('xdebug.max_nesting_level', 3000);
+
+// Disable Xdebug var_dump() output truncation
+ini_set('xdebug.var_display_max_children', -1);
+ini_set('xdebug.var_display_max_data', -1);
+ini_set('xdebug.var_display_max_depth', -1);
+
+list($operations, $files, $attributes) = parseArgs($argv);
+
+/* Dump nodes by default */
+if (empty($operations)) {
+    $operations[] = 'dump';
+}
+
+if (empty($files)) {
+    showHelp("Must specify at least one file.");
+}
+
+$lexer = new PhpParser\Lexer\Emulative(['usedAttributes' => [
+    'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments'
+]]);
+$parser = (new PhpParser\ParserFactory)->create(
+    PhpParser\ParserFactory::PREFER_PHP7,
+    $lexer
+);
+$dumper = new PhpParser\NodeDumper([
+    'dumpComments' => true,
+    'dumpPositions' => $attributes['with-positions'],
+]);
+$prettyPrinter = new PhpParser\PrettyPrinter\Standard;
+
+$traverser = new PhpParser\NodeTraverser();
+$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver);
+
+foreach ($files as $file) {
+    if (strpos($file, '<?php') === 0) {
+        $code = $file;
+        fwrite(STDERR, "====> Code $code\n");
+    } else {
+        if (!file_exists($file)) {
+            fwrite(STDERR, "File $file does not exist.\n");
+            exit(1);
+        }
+
+        $code = file_get_contents($file);
+        fwrite(STDERR, "====> File $file:\n");
+    }
+
+    if ($attributes['with-recovery']) {
+        $errorHandler = new PhpParser\ErrorHandler\Collecting;
+        $stmts = $parser->parse($code, $errorHandler);
+        foreach ($errorHandler->getErrors() as $error) {
+            $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
+            fwrite(STDERR, $message . "\n");
+        }
+        if (null === $stmts) {
+            continue;
+        }
+    } else {
+        try {
+            $stmts = $parser->parse($code);
+        } catch (PhpParser\Error $error) {
+            $message = formatErrorMessage($error, $code, $attributes['with-column-info']);
+            fwrite(STDERR, $message . "\n");
+            exit(1);
+        }
+    }
+
+    foreach ($operations as $operation) {
+        if ('dump' === $operation) {
+            fwrite(STDERR, "==> Node dump:\n");
+            echo $dumper->dump($stmts, $code), "\n";
+        } elseif ('pretty-print' === $operation) {
+            fwrite(STDERR, "==> Pretty print:\n");
+            echo $prettyPrinter->prettyPrintFile($stmts), "\n";
+        } elseif ('json-dump' === $operation) {
+            fwrite(STDERR, "==> JSON dump:\n");
+            echo json_encode($stmts, JSON_PRETTY_PRINT), "\n";
+        } elseif ('var-dump' === $operation) {
+            fwrite(STDERR, "==> var_dump():\n");
+            var_dump($stmts);
+        } elseif ('resolve-names' === $operation) {
+            fwrite(STDERR, "==> Resolved names.\n");
+            $stmts = $traverser->traverse($stmts);
+        }
+    }
+}
+
+function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) {
+    if ($withColumnInfo && $e->hasColumnInfo()) {
+        return $e->getMessageWithColumnInfo($code);
+    } else {
+        return $e->getMessage();
+    }
+}
+
+function showHelp($error = '') {
+    if ($error) {
+        fwrite(STDERR, $error . "\n\n");
+    }
+    fwrite($error ? STDERR : STDOUT, <<<OUTPUT
+Usage: php-parse [operations] file1.php [file2.php ...]
+   or: php-parse [operations] "<?php code"
+Turn PHP source code into an abstract syntax tree.
+
+Operations is a list of the following options (--dump by default):
+
+    -d, --dump              Dump nodes using NodeDumper
+    -p, --pretty-print      Pretty print file using PrettyPrinter\Standard
+    -j, --json-dump         Print json_encode() result
+        --var-dump          var_dump() nodes (for exact structure)
+    -N, --resolve-names     Resolve names using NodeVisitor\NameResolver
+    -c, --with-column-info  Show column-numbers for errors (if available)
+    -P, --with-positions    Show positions in node dumps
+    -r, --with-recovery     Use parsing with error recovery
+    -h, --help              Display this page
+
+Example:
+    php-parse -d -p -N -d file.php
+
+    Dumps nodes, pretty prints them, then resolves names and dumps them again.
+
+
+OUTPUT
+    );
+    exit($error ? 1 : 0);
+}
+
+function parseArgs($args) {
+    $operations = [];
+    $files = [];
+    $attributes = [
+        'with-column-info' => false,
+        'with-positions' => false,
+        'with-recovery' => false,
+    ];
+
+    array_shift($args);
+    $parseOptions = true;
+    foreach ($args as $arg) {
+        if (!$parseOptions) {
+            $files[] = $arg;
+            continue;
+        }
+
+        switch ($arg) {
+            case '--dump':
+            case '-d':
+                $operations[] = 'dump';
+                break;
+            case '--pretty-print':
+            case '-p':
+                $operations[] = 'pretty-print';
+                break;
+            case '--json-dump':
+            case '-j':
+                $operations[] = 'json-dump';
+                break;
+            case '--var-dump':
+                $operations[] = 'var-dump';
+                break;
+            case '--resolve-names':
+            case '-N';
+                $operations[] = 'resolve-names';
+                break;
+            case '--with-column-info':
+            case '-c';
+                $attributes['with-column-info'] = true;
+                break;
+            case '--with-positions':
+            case '-P':
+                $attributes['with-positions'] = true;
+                break;
+            case '--with-recovery':
+            case '-r':
+                $attributes['with-recovery'] = true;
+                break;
+            case '--help':
+            case '-h';
+                showHelp();
+                break;
+            case '--':
+                $parseOptions = false;
+                break;
+            default:
+                if ($arg[0] === '-') {
+                    showHelp("Invalid operation $arg.");
+                } else {
+                    $files[] = $arg;
+                }
+        }
+    }
+
+    return [$operations, $files, $attributes];
+}

+ 107 - 0
vendor/bin/phpunit

@@ -0,0 +1,107 @@
+#!/usr/bin/env php
+<?php declare(strict_types=1);
+/*
+ * This file is part of PHPUnit.
+ *
+ * (c) Sebastian Bergmann <sebastian@phpunit.de>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if (!version_compare(PHP_VERSION, PHP_VERSION, '=')) {
+    fwrite(
+        STDERR,
+        sprintf(
+            '%s declares an invalid value for PHP_VERSION.' . PHP_EOL .
+            'This breaks fundamental functionality such as version_compare().' . PHP_EOL .
+            'Please use a different PHP interpreter.' . PHP_EOL,
+
+            PHP_BINARY
+        )
+    );
+
+    die(1);
+}
+
+if (version_compare('7.3.0', PHP_VERSION, '>')) {
+    fwrite(
+        STDERR,
+        sprintf(
+            'This version of PHPUnit requires PHP >= 7.3.' . PHP_EOL .
+            'You are using PHP %s (%s).' . PHP_EOL,
+            PHP_VERSION,
+            PHP_BINARY
+        )
+    );
+
+    die(1);
+}
+
+$requiredExtensions = ['dom', 'json', 'libxml', 'mbstring', 'tokenizer', 'xml', 'xmlwriter'];
+
+$unavailableExtensions = array_filter(
+    $requiredExtensions,
+    static function ($extension) {
+        return !extension_loaded($extension);
+    }
+);
+
+if ([] !== $unavailableExtensions) {
+    fwrite(
+        STDERR,
+        sprintf(
+            'PHPUnit requires the "%s" extensions, but the "%s" %s not available.' . PHP_EOL,
+            implode('", "', $requiredExtensions),
+            implode('", "', $unavailableExtensions),
+            count($unavailableExtensions) === 1 ? 'extension is' : 'extensions are'
+        )
+    );
+
+    die(1);
+}
+
+unset($requiredExtensions, $unavailableExtensions);
+
+if (!ini_get('date.timezone')) {
+    ini_set('date.timezone', 'UTC');
+}
+
+if (isset($GLOBALS['_composer_autoload_path'])) {
+    define('PHPUNIT_COMPOSER_INSTALL', $GLOBALS['_composer_autoload_path']);
+
+    unset($GLOBALS['_composer_autoload_path']);
+} else {
+    foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/../vendor/autoload.php', __DIR__ . '/vendor/autoload.php') as $file) {
+        if (file_exists($file)) {
+            define('PHPUNIT_COMPOSER_INSTALL', $file);
+
+            break;
+        }
+    }
+
+    unset($file);
+}
+
+if (!defined('PHPUNIT_COMPOSER_INSTALL')) {
+    fwrite(
+        STDERR,
+        'You need to set up the project dependencies using Composer:' . PHP_EOL . PHP_EOL .
+        '    composer install' . PHP_EOL . PHP_EOL .
+        'You can learn all about Composer on https://getcomposer.org/.' . PHP_EOL
+    );
+
+    die(1);
+}
+
+$options = getopt('', array('prepend:'));
+
+if (isset($options['prepend'])) {
+    require $options['prepend'];
+}
+
+unset($options);
+
+require PHPUNIT_COMPOSER_INSTALL;
+
+PHPUnit\TextUI\Command::main();

+ 78 - 0
vendor/bin/pinyin

@@ -0,0 +1,78 @@
+#!/usr/bin/env php
+<?php
+
+require __DIR__ . '/../vendor/autoload.php';
+require __DIR__ . '/utils.php';
+
+use Overtrue\Pinyin\Pinyin;
+
+$methods = ['sentence','fullSentence','name','passportName','phrase','permalink','polyphones','chars','abbr','nameAbbr'];
+$method = 'sentence';
+$inputOptions = [];
+$methodAsString = implode('/', $methods);
+
+$help = <<<"HELP"
+Usage:
+    ./pinyin [chinese] [method] [options]
+Options:
+    -j, --json               输出 JSON 格式.
+    -c, --compact            不格式化输出 JSON.
+    -m, --method=[method]    转换方式,可选:{$methodAsString}.
+    --no-tone                不使用音调.
+    --tone-style=[style]     音调风格,可选值:symbol/none/number, default: none.
+    -h, --help               显示帮助.
+HELP;
+
+function has_option($option, $alias = null): bool
+{
+    global $inputOptions;
+
+    if ($alias) {
+        return array_key_exists($option, $inputOptions) || array_key_exists($alias, $inputOptions);
+    }
+
+    return array_key_exists($option, $inputOptions);
+}
+
+function get_option($option, $default = null, $alias = null): ?string
+{
+    global $inputOptions;
+
+    if ($alias) {
+        return $inputOptions[$option] ?? $inputOptions[$alias] ?? $default;
+    }
+
+    return $inputOptions[$option] ?? $default;
+}
+
+$inputOptions = parse_options($argv);
+$input = $inputOptions[0] ?? null;
+
+if (empty($input) || has_option('help', 'h')) {
+    echo $help;
+    exit(0);
+}
+
+$method = get_option('method', $method, 'm');
+$toneStyle = has_option('no-tone') ? 'none' : get_option('tone-style', 'none');
+
+if (! in_array($method, $methods)) {
+    echo "Method '{$method}' is not supported.\n";
+    exit(1);
+}
+
+$result = Pinyin::$method($input, $method === 'permalink' ? '-' : $toneStyle);
+
+$toJson = has_option('json', 'j') || in_array($method, ['polyphones']);
+
+if ($toJson) {
+    $options = JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT;
+
+    if (has_option('compact', 'c')) {
+        $options = 0;
+    }
+
+    $result = json_encode($result, $options);
+}
+
+echo $result, "\n";

+ 148 - 0
vendor/bin/psysh

@@ -0,0 +1,148 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * This file is part of Psy Shell.
+ *
+ * (c) 2012-2023 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+// Try to find an autoloader for a local psysh version.
+// We'll wrap this whole mess in a Closure so it doesn't leak any globals.
+call_user_func(function () {
+    $cwd = null;
+
+    // Find the cwd arg (if present)
+    $argv = isset($_SERVER['argv']) ? $_SERVER['argv'] : array();
+    foreach ($argv as $i => $arg) {
+        if ($arg === '--cwd') {
+            if ($i >= count($argv) - 1) {
+                fwrite(STDERR, 'Missing --cwd argument.' . PHP_EOL);
+                exit(1);
+            }
+            $cwd = $argv[$i + 1];
+            break;
+        }
+
+        if (preg_match('/^--cwd=/', $arg)) {
+            $cwd = substr($arg, 6);
+            break;
+        }
+    }
+
+    // Or fall back to the actual cwd
+    if (!isset($cwd)) {
+        $cwd = getcwd();
+    }
+
+    $cwd = str_replace('\\', '/', $cwd);
+
+    $chunks = explode('/', $cwd);
+    while (!empty($chunks)) {
+        $path = implode('/', $chunks);
+        $prettyPath = $path;
+        if (isset($_SERVER['HOME']) && $_SERVER['HOME']) {
+            $prettyPath = preg_replace('/^' . preg_quote($_SERVER['HOME'], '/') . '/', '~', $path);
+        }
+
+        // Find composer.json
+        if (is_file($path . '/composer.json')) {
+            if ($cfg = json_decode(file_get_contents($path . '/composer.json'), true)) {
+                if (isset($cfg['name']) && $cfg['name'] === 'psy/psysh') {
+                    // We're inside the psysh project. Let's use the local Composer autoload.
+                    if (is_file($path . '/vendor/autoload.php')) {
+                        if (realpath($path) !== realpath(__DIR__ . '/..')) {
+                            fwrite(STDERR, 'Using local PsySH version at ' . $prettyPath . PHP_EOL);
+                        }
+
+                        require $path . '/vendor/autoload.php';
+                    }
+
+                    return;
+                }
+            }
+        }
+
+        // Or a composer.lock
+        if (is_file($path . '/composer.lock')) {
+            if ($cfg = json_decode(file_get_contents($path . '/composer.lock'), true)) {
+                foreach (array_merge($cfg['packages'], $cfg['packages-dev']) as $pkg) {
+                    if (isset($pkg['name']) && $pkg['name'] === 'psy/psysh') {
+                        // We're inside a project which requires psysh. We'll use the local Composer autoload.
+                        if (is_file($path . '/vendor/autoload.php')) {
+                            if (realpath($path . '/vendor') !== realpath(__DIR__ . '/../../..')) {
+                                fwrite(STDERR, 'Using local PsySH version at ' . $prettyPath . PHP_EOL);
+                            }
+
+                            require $path . '/vendor/autoload.php';
+                        }
+
+                        return;
+                    }
+                }
+            }
+        }
+
+        array_pop($chunks);
+    }
+});
+
+// We didn't find an autoloader for a local version, so use the autoloader that
+// came with this script.
+if (!class_exists('Psy\Shell')) {
+/* <<< */
+    if (is_file(__DIR__ . '/../vendor/autoload.php')) {
+        require __DIR__ . '/../vendor/autoload.php';
+    } elseif (is_file(__DIR__ . '/../../../autoload.php')) {
+        require __DIR__ . '/../../../autoload.php';
+    } else {
+        fwrite(STDERR, 'PsySH dependencies not found, be sure to run `composer install`.' . PHP_EOL);
+        fwrite(STDERR, 'See https://getcomposer.org to get Composer.' . PHP_EOL);
+        exit(1);
+    }
+/* >>> */
+}
+
+// If the psysh binary was included directly, assume they just wanted an
+// autoloader and bail early.
+//
+// Keep this PHP 5.3 and 5.4 code around for a while in case someone is using a
+// globally installed psysh as a bin launcher for older local versions.
+if (version_compare(PHP_VERSION, '5.3.6', '<')) {
+    $trace = debug_backtrace();
+} elseif (version_compare(PHP_VERSION, '5.4.0', '<')) {
+    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
+} else {
+    $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
+}
+
+if (Psy\Shell::isIncluded($trace)) {
+    unset($trace);
+
+    return;
+}
+
+// Clean up after ourselves.
+unset($trace);
+
+// If the local version is too old, we can't do this
+if (!function_exists('Psy\bin')) {
+    $argv = isset($_SERVER['argv']) ? $_SERVER['argv'] : array();
+    $first = array_shift($argv);
+    if (preg_match('/php(\.exe)?$/', $first)) {
+        array_shift($argv);
+    }
+    array_unshift($argv, 'vendor/bin/psysh');
+
+    fwrite(STDERR, 'A local PsySH dependency was found, but it cannot be loaded. Please update to' . PHP_EOL);
+    fwrite(STDERR, 'the latest version, or run the local copy directly, e.g.:' . PHP_EOL);
+    fwrite(STDERR, PHP_EOL);
+    fwrite(STDERR, '    ' . implode(' ', $argv) . PHP_EOL);
+    exit(1);
+}
+
+// And go!
+call_user_func(Psy\bin());

+ 576 - 0
vendor/bin/sail

@@ -0,0 +1,576 @@
+#!/usr/bin/env bash
+
+UNAMEOUT="$(uname -s)"
+
+# Verify operating system is supported...
+case "${UNAMEOUT}" in
+    Linux*)             MACHINE=linux;;
+    Darwin*)            MACHINE=mac;;
+    *)                  MACHINE="UNKNOWN"
+esac
+
+if [ "$MACHINE" == "UNKNOWN" ]; then
+    echo "Unsupported operating system [$(uname -s)]. Laravel Sail supports macOS, Linux, and Windows (WSL2)." >&2
+
+    exit 1
+fi
+
+# Determine if stdout is a terminal...
+if test -t 1; then
+    # Determine if colors are supported...
+    ncolors=$(tput colors)
+
+    if test -n "$ncolors" && test "$ncolors" -ge 8; then
+        BOLD="$(tput bold)"
+        YELLOW="$(tput setaf 3)"
+        GREEN="$(tput setaf 2)"
+        NC="$(tput sgr0)"
+    fi
+fi
+
+# Function that prints the available commands...
+function display_help {
+    echo "Laravel Sail"
+    echo
+    echo "${YELLOW}Usage:${NC}" >&2
+    echo "  sail COMMAND [options] [arguments]"
+    echo
+    echo "Unknown commands are passed to the docker-compose binary."
+    echo
+    echo "${YELLOW}docker-compose Commands:${NC}"
+    echo "  ${GREEN}sail up${NC}        Start the application"
+    echo "  ${GREEN}sail up -d${NC}     Start the application in the background"
+    echo "  ${GREEN}sail stop${NC}      Stop the application"
+    echo "  ${GREEN}sail restart${NC}   Restart the application"
+    echo "  ${GREEN}sail ps${NC}        Display the status of all containers"
+    echo
+    echo "${YELLOW}Artisan Commands:${NC}"
+    echo "  ${GREEN}sail artisan ...${NC}          Run an Artisan command"
+    echo "  ${GREEN}sail artisan queue:work${NC}"
+    echo
+    echo "${YELLOW}PHP Commands:${NC}"
+    echo "  ${GREEN}sail php ...${NC}   Run a snippet of PHP code"
+    echo "  ${GREEN}sail php -v${NC}"
+    echo
+    echo "${YELLOW}Composer Commands:${NC}"
+    echo "  ${GREEN}sail composer ...${NC}                       Run a Composer command"
+    echo "  ${GREEN}sail composer require laravel/sanctum${NC}"
+    echo
+    echo "${YELLOW}Node Commands:${NC}"
+    echo "  ${GREEN}sail node ...${NC}         Run a Node command"
+    echo "  ${GREEN}sail node --version${NC}"
+    echo
+    echo "${YELLOW}NPM Commands:${NC}"
+    echo "  ${GREEN}sail npm ...${NC}        Run a npm command"
+    echo "  ${GREEN}sail npx${NC}            Run a npx command"
+    echo "  ${GREEN}sail npm run prod${NC}"
+    echo
+    echo "${YELLOW}PNPM Commands:${NC}"
+    echo "  ${GREEN}sail pnpm ...${NC}        Run a pnpm command"
+    echo "  ${GREEN}sail pnpx${NC}            Run a pnpx command"
+    echo "  ${GREEN}sail pnpm run prod${NC}"
+    echo
+    echo "${YELLOW}Yarn Commands:${NC}"
+    echo "  ${GREEN}sail yarn ...${NC}        Run a Yarn command"
+    echo "  ${GREEN}sail yarn run prod${NC}"
+    echo
+    echo "${YELLOW}Bun Commands:${NC}"
+    echo "  ${GREEN}sail bun ...${NC}        Run a bun command"
+    echo "  ${GREEN}sail bunx${NC}           Run a bunx command"
+    echo "  ${GREEN}sail bun run prod${NC}"
+    echo
+    echo "${YELLOW}Database Commands:${NC}"
+    echo "  ${GREEN}sail mysql${NC}     Start a MySQL CLI session within the 'mysql' container"
+    echo "  ${GREEN}sail mariadb${NC}   Start a MySQL CLI session within the 'mariadb' container"
+    echo "  ${GREEN}sail psql${NC}      Start a PostgreSQL CLI session within the 'pgsql' container"
+    echo "  ${GREEN}sail redis${NC}     Start a Redis CLI session within the 'redis' container"
+    echo
+    echo "${YELLOW}Debugging:${NC}"
+    echo "  ${GREEN}sail debug ...${NC}          Run an Artisan command in debug mode"
+    echo "  ${GREEN}sail debug queue:work${NC}"
+    echo
+    echo "${YELLOW}Running Tests:${NC}"
+    echo "  ${GREEN}sail test${NC}          Run the PHPUnit tests via the Artisan test command"
+    echo "  ${GREEN}sail phpunit ...${NC}   Run PHPUnit"
+    echo "  ${GREEN}sail pest ...${NC}      Run Pest"
+    echo "  ${GREEN}sail pint ...${NC}      Run Pint"
+    echo "  ${GREEN}sail dusk${NC}          Run the Dusk tests (Requires the laravel/dusk package)"
+    echo "  ${GREEN}sail dusk:fails${NC}    Re-run previously failed Dusk tests (Requires the laravel/dusk package)"
+    echo
+    echo "${YELLOW}Container CLI:${NC}"
+    echo "  ${GREEN}sail shell${NC}        Start a shell session within the application container"
+    echo "  ${GREEN}sail bash${NC}         Alias for 'sail shell'"
+    echo "  ${GREEN}sail root-shell${NC}   Start a root shell session within the application container"
+    echo "  ${GREEN}sail root-bash${NC}    Alias for 'sail root-shell'"
+    echo "  ${GREEN}sail tinker${NC}       Start a new Laravel Tinker session"
+    echo
+    echo "${YELLOW}Sharing:${NC}"
+    echo "  ${GREEN}sail share${NC}   Share the application publicly via a temporary URL"
+    echo "  ${GREEN}sail open${NC}    Open the site in your browser"
+    echo
+    echo "${YELLOW}Binaries:${NC}"
+    echo "  ${GREEN}sail bin ...${NC}   Run Composer binary scripts from the vendor/bin directory"
+    echo
+    echo "${YELLOW}Customization:${NC}"
+    echo "  ${GREEN}sail artisan sail:publish${NC}   Publish the Sail configuration files"
+    echo "  ${GREEN}sail build --no-cache${NC}       Rebuild all of the Sail containers"
+
+    exit 1
+}
+
+# Proxy the "help" command...
+if [ $# -gt 0 ]; then
+    if [ "$1" == "help" ] || [ "$1" == "-h" ] || [ "$1" == "-help" ] || [ "$1" == "--help" ]; then
+        display_help
+    fi
+else
+    display_help
+fi
+
+# Source the ".env" file so Laravel's environment variables are available...
+# shellcheck source=/dev/null
+if [ -n "$APP_ENV" ] && [ -f ./.env."$APP_ENV" ]; then
+  source ./.env."$APP_ENV";
+elif [ -f ./.env ]; then
+  source ./.env;
+fi
+
+# Define environment variables...
+export APP_PORT=${APP_PORT:-80}
+export APP_SERVICE=${APP_SERVICE:-"laravel.test"}
+export DB_PORT=${DB_PORT:-3306}
+export WWWUSER=${WWWUSER:-$UID}
+export WWWGROUP=${WWWGROUP:-$(id -g)}
+
+export SAIL_FILES=${SAIL_FILES:-""}
+export SAIL_SHARE_DASHBOARD=${SAIL_SHARE_DASHBOARD:-4040}
+export SAIL_SHARE_SERVER_HOST=${SAIL_SHARE_SERVER_HOST:-"laravel-sail.site"}
+export SAIL_SHARE_SERVER_PORT=${SAIL_SHARE_SERVER_PORT:-8080}
+export SAIL_SHARE_SUBDOMAIN=${SAIL_SHARE_SUBDOMAIN:-""}
+export SAIL_SHARE_DOMAIN=${SAIL_SHARE_DOMAIN:-"$SAIL_SHARE_SERVER_HOST"}
+export SAIL_SHARE_SERVER=${SAIL_SHARE_SERVER:-""}
+
+# Function that outputs Sail is not running...
+function sail_is_not_running {
+    echo "${BOLD}Sail is not running.${NC}" >&2
+    echo "" >&2
+    echo "${BOLD}You may Sail using the following commands:${NC} './vendor/bin/sail up' or './vendor/bin/sail up -d'" >&2
+
+    exit 1
+}
+
+# Define Docker Compose command prefix...
+if docker compose &> /dev/null; then
+    DOCKER_COMPOSE=(docker compose)
+else
+    DOCKER_COMPOSE=(docker-compose)
+fi
+
+if [ -n "$SAIL_FILES" ]; then
+    # Convert SAIL_FILES to an array...
+    IFS=':' read -ra SAIL_FILES <<< "$SAIL_FILES"
+
+    for FILE in "${SAIL_FILES[@]}"; do
+        if [ -f "$FILE" ]; then
+            DOCKER_COMPOSE+=(-f "$FILE")
+        else
+            echo "${BOLD}Unable to find Docker Compose file: '${FILE}'${NC}" >&2
+
+            exit 1
+        fi
+    done
+fi
+
+EXEC="yes"
+
+if [ -z "$SAIL_SKIP_CHECKS" ]; then
+    # Ensure that Docker is running...
+    if ! docker info > /dev/null 2>&1; then
+        echo "${BOLD}Docker is not running.${NC}" >&2
+
+        exit 1
+    fi
+
+    # Determine if Sail is currently up...
+    if "${DOCKER_COMPOSE[@]}" ps "$APP_SERVICE" 2>&1 | grep 'Exit\|exited'; then
+        echo "${BOLD}Shutting down old Sail processes...${NC}" >&2
+
+        "${DOCKER_COMPOSE[@]}" down > /dev/null 2>&1
+
+        EXEC="no"
+    elif [ -z "$("${DOCKER_COMPOSE[@]}" ps -q)" ]; then
+        EXEC="no"
+    fi
+fi
+
+ARGS=()
+
+# Proxy PHP commands to the "php" binary on the application container...
+if [ "$1" == "php" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" "php" "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy vendor binary commands on the application container...
+elif [ "$1" == "bin" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" ./vendor/bin/"$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy docker-compose commands to the docker-compose binary on the application container...
+elif [ "$1" == "docker-compose" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" "${DOCKER_COMPOSE[@]}")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy Composer commands to the "composer" binary on the application container...
+elif [ "$1" == "composer" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" "composer" "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy Artisan commands to the "artisan" binary on the application container...
+elif [ "$1" == "artisan" ] || [ "$1" == "art" ] || [ "$1" == "a" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php artisan "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "debug" command to the "php artisan" binary on the application container with xdebug enabled...
+elif [ "$1" == "debug" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail -e XDEBUG_SESSION=1)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php artisan "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "test" command to the "php artisan test" Artisan command...
+elif [ "$1" == "test" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php artisan test "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "phpunit" command to "php vendor/bin/phpunit"...
+elif [ "$1" == "phpunit" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php vendor/bin/phpunit "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "pest" command to "php vendor/bin/pest"...
+elif [ "$1" == "pest" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php vendor/bin/pest "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "pint" command to "php vendor/bin/pint"...
+elif [ "$1" == "pint" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php vendor/bin/pint "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "dusk" command to the "php artisan dusk" Artisan command...
+elif [ "$1" == "dusk" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=(-e "APP_URL=http://${APP_SERVICE}")
+        ARGS+=(-e "DUSK_DRIVER_URL=http://selenium:4444/wd/hub")
+        ARGS+=("$APP_SERVICE" php artisan dusk "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy the "dusk:fails" command to the "php artisan dusk:fails" Artisan command...
+elif [ "$1" == "dusk:fails" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=(-e "APP_URL=http://${APP_SERVICE}")
+        ARGS+=(-e "DUSK_DRIVER_URL=http://selenium:4444/wd/hub")
+        ARGS+=("$APP_SERVICE" php artisan dusk:fails "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a Laravel Tinker session within the application container...
+elif [ "$1" == "tinker" ] ; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" php artisan tinker)
+    else
+        sail_is_not_running
+    fi
+
+# Proxy Node commands to the "node" binary on the application container...
+elif [ "$1" == "node" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" node "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy NPM commands to the "npm" binary on the application container...
+elif [ "$1" == "npm" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" npm "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy NPX commands to the "npx" binary on the application container...
+elif [ "$1" == "npx" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" npx "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy PNPM commands to the "pnpm" binary on the application container...
+elif [ "$1" == "pnpm" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" pnpm "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy PNPX commands to the "pnpx" binary on the application container...
+elif [ "$1" == "pnpx" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" pnpx "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy YARN commands to the "yarn" binary on the application container...
+elif [ "$1" == "yarn" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" yarn "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy Bun commands to the "bun" binary on the application container...
+elif [ "$1" == "bun" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" bun "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Proxy Bun X commands to the "bunx" binary on the application container...
+elif [ "$1" == "bunx" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" bunx "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a MySQL CLI terminal session within the "mysql" container...
+elif [ "$1" == "mysql" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=(mysql bash -c)
+        ARGS+=("MYSQL_PWD=\${MYSQL_PASSWORD} mysql -u \${MYSQL_USER} \${MYSQL_DATABASE}")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a MySQL CLI terminal session within the "mariadb" container...
+elif [ "$1" == "mariadb" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=(mariadb bash -c)
+        ARGS+=("MYSQL_PWD=\${MYSQL_PASSWORD} mysql -u \${MYSQL_USER} \${MYSQL_DATABASE}")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a PostgreSQL CLI terminal session within the "pgsql" container...
+elif [ "$1" == "psql" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=(pgsql bash -c)
+        ARGS+=("PGPASSWORD=\${PGPASSWORD} psql -U \${POSTGRES_USER} \${POSTGRES_DB}")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a Bash shell within the application container...
+elif [ "$1" == "shell" ] || [ "$1" == "bash" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u sail)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" bash "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a root user Bash shell within the application container...
+elif [ "$1" == "root-shell" ] || [ "$1" == "root-bash" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec -u root)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=("$APP_SERVICE" bash "$@")
+    else
+        sail_is_not_running
+    fi
+
+# Initiate a Redis CLI terminal session within the "redis" container...
+elif [ "$1" == "redis" ] ; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        ARGS+=(exec)
+        [ ! -t 0 ] && ARGS+=(-T)
+        ARGS+=(redis redis-cli)
+    else
+        sail_is_not_running
+    fi
+
+# Share the site...
+elif [ "$1" == "share" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        docker run --init --rm -p "$SAIL_SHARE_DASHBOARD":4040 -t beyondcodegmbh/expose-server:latest share http://host.docker.internal:"$APP_PORT" \
+            --server-host="$SAIL_SHARE_SERVER_HOST" \
+            --server-port="$SAIL_SHARE_SERVER_PORT" \
+            --auth="$SAIL_SHARE_TOKEN" \
+            --server="$SAIL_SHARE_SERVER" \
+            --subdomain="$SAIL_SHARE_SUBDOMAIN" \
+            --domain="$SAIL_SHARE_DOMAIN" \
+            "$@"
+
+        exit
+    else
+        sail_is_not_running
+    fi
+
+# Open the site...
+elif [ "$1" == "open" ]; then
+    shift 1
+
+    if [ "$EXEC" == "yes" ]; then
+        open "$APP_URL"
+
+        exit
+    else
+        sail_is_not_running
+    fi
+
+# Pass unknown commands to the "docker-compose" binary...
+else
+    ARGS+=("$@")
+fi
+
+# Run Docker Compose with the defined arguments...
+"${DOCKER_COMPOSE[@]}" "${ARGS[@]}"

+ 67 - 0
vendor/bin/var-dump-server

@@ -0,0 +1,67 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if ('cli' !== PHP_SAPI) {
+    throw new Exception('This script must be run from the command line.');
+}
+
+/**
+ * Starts a dump server to collect and output dumps on a single place with multiple formats support.
+ *
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Logger\ConsoleLogger;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\VarDumper\Command\ServerDumpCommand;
+use Symfony\Component\VarDumper\Server\DumpServer;
+
+function includeIfExists(string $file): bool
+{
+    return file_exists($file) && include $file;
+}
+
+if (
+    !includeIfExists(__DIR__ . '/../../../../autoload.php') &&
+    !includeIfExists(__DIR__ . '/../../vendor/autoload.php') &&
+    !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')
+) {
+    fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL);
+    exit(1);
+}
+
+if (!class_exists(Application::class)) {
+    fwrite(STDERR, 'You need the "symfony/console" component in order to run the VarDumper server.'.PHP_EOL);
+    exit(1);
+}
+
+$input = new ArgvInput();
+$output = new ConsoleOutput();
+$defaultHost = '127.0.0.1:9912';
+$host = $input->getParameterOption(['--host'], $_SERVER['VAR_DUMPER_SERVER'] ?? $defaultHost, true);
+$logger = interface_exists(LoggerInterface::class) ? new ConsoleLogger($output->getErrorOutput()) : null;
+
+$app = new Application();
+
+$app->getDefinition()->addOption(
+    new InputOption('--host', null, InputOption::VALUE_REQUIRED, 'The address the server should listen to', $defaultHost)
+);
+
+$app->add($command = new ServerDumpCommand(new DumpServer($host, $logger)))
+    ->getApplication()
+    ->setDefaultCommand($command->getName(), true)
+    ->run($input, $output)
+;

+ 49 - 0
vendor/bin/yaml-lint

@@ -0,0 +1,49 @@
+#!/usr/bin/env php
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+if ('cli' !== \PHP_SAPI) {
+    throw new Exception('This script must be run from the command line.');
+}
+
+/**
+ * Runs the Yaml lint command.
+ *
+ * @author Jan Schädlich <jan.schaedlich@sensiolabs.de>
+ */
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Yaml\Command\LintCommand;
+
+function includeIfExists(string $file): bool
+{
+    return file_exists($file) && include $file;
+}
+
+if (
+    !includeIfExists(__DIR__ . '/../../../../autoload.php') &&
+    !includeIfExists(__DIR__ . '/../../vendor/autoload.php') &&
+    !includeIfExists(__DIR__ . '/../../../../../../vendor/autoload.php')
+) {
+    fwrite(STDERR, 'Install dependencies using Composer.'.PHP_EOL);
+    exit(1);
+}
+
+if (!class_exists(Application::class)) {
+    fwrite(STDERR, 'You need the "symfony/console" component in order to run the Yaml linter.'.PHP_EOL);
+    exit(1);
+}
+
+(new Application())->add($command = new LintCommand())
+    ->getApplication()
+    ->setDefaultCommand($command->getName(), true)
+    ->run()
+;

+ 166 - 0
vendor/box/spout/LICENSE

@@ -0,0 +1,166 @@
+                             Apache License
+                       Version 2.0, January 2004
+                    http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+  "License" shall mean the terms and conditions for use, reproduction,
+  and distribution as defined by Sections 1 through 9 of this document.
+  "Licensor" shall mean the copyright owner or entity authorized by
+  the copyright owner that is granting the License.
+  "Legal Entity" shall mean the union of the acting entity and all
+  other entities that control, are controlled by, or are under common
+  control with that entity. For the purposes of this definition,
+  "control" means (i) the power, direct or indirect, to cause the
+  direction or management of such entity, whether by contract or
+  otherwise, or (ii) ownership of fifty percent (50%) or more of the
+  outstanding shares, or (iii) beneficial ownership of such entity.
+  "You" (or "Your") shall mean an individual or Legal Entity
+  exercising permissions granted by this License.
+  "Source" form shall mean the preferred form for making modifications,
+  including but not limited to software source code, documentation
+  source, and configuration files.
+  "Object" form shall mean any form resulting from mechanical
+  transformation or translation of a Source form, including but
+  not limited to compiled object code, generated documentation,
+  and conversions to other media types.
+  "Work" shall mean the work of authorship, whether in Source or
+  Object form, made available under the License, as indicated by a
+  copyright notice that is included in or attached to the work
+  (an example is provided in the Appendix below).
+  "Derivative Works" shall mean any work, whether in Source or Object
+  form, that is based on (or derived from) the Work and for which the
+  editorial revisions, annotations, elaborations, or other modifications
+  represent, as a whole, an original work of authorship. For the purposes
+  of this License, Derivative Works shall not include works that remain
+  separable from, or merely link (or bind by name) to the interfaces of,
+  the Work and Derivative Works thereof.
+  "Contribution" shall mean any work of authorship, including
+  the original version of the Work and any modifications or additions
+  to that Work or Derivative Works thereof, that is intentionally
+  submitted to Licensor for inclusion in the Work by the copyright owner
+  or by an individual or Legal Entity authorized to submit on behalf of
+  the copyright owner. For the purposes of this definition, "submitted"
+  means any form of electronic, verbal, or written communication sent
+  to the Licensor or its representatives, including but not limited to
+  communication on electronic mailing lists, source code control systems,
+  and issue tracking systems that are managed by, or on behalf of, the
+  Licensor for the purpose of discussing and improving the Work, but
+  excluding communication that is conspicuously marked or otherwise
+  designated in writing by the copyright owner as "Not a Contribution."
+  "Contributor" shall mean Licensor and any individual or Legal Entity
+  on behalf of whom a Contribution has been received by Licensor and
+  subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+  this License, each Contributor hereby grants to You a perpetual,
+  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+  copyright license to reproduce, prepare Derivative Works of,
+  publicly display, publicly perform, sublicense, and distribute the
+  Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+  this License, each Contributor hereby grants to You a perpetual,
+  worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+  (except as stated in this section) patent license to make, have made,
+  use, offer to sell, sell, import, and otherwise transfer the Work,
+  where such license applies only to those patent claims licensable
+  by such Contributor that are necessarily infringed by their
+  Contribution(s) alone or by combination of their Contribution(s)
+  with the Work to which such Contribution(s) was submitted. If You
+  institute patent litigation against any entity (including a
+  cross-claim or counterclaim in a lawsuit) alleging that the Work
+  or a Contribution incorporated within the Work constitutes direct
+  or contributory patent infringement, then any patent licenses
+  granted to You under this License for that Work shall terminate
+  as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+  Work or Derivative Works thereof in any medium, with or without
+  modifications, and in Source or Object form, provided that You
+  meet the following conditions:
+
+  (a) You must give any other recipients of the Work or
+      Derivative Works a copy of this License; and
+
+  (b) You must cause any modified files to carry prominent notices
+      stating that You changed the files; and
+
+  (c) You must retain, in the Source form of any Derivative Works
+      that You distribute, all copyright, patent, trademark, and
+      attribution notices from the Source form of the Work,
+      excluding those notices that do not pertain to any part of
+      the Derivative Works; and
+
+  (d) If the Work includes a "NOTICE" text file as part of its
+      distribution, then any Derivative Works that You distribute must
+      include a readable copy of the attribution notices contained
+      within such NOTICE file, excluding those notices that do not
+      pertain to any part of the Derivative Works, in at least one
+      of the following places: within a NOTICE text file distributed
+      as part of the Derivative Works; within the Source form or
+      documentation, if provided along with the Derivative Works; or,
+      within a display generated by the Derivative Works, if and
+      wherever such third-party notices normally appear. The contents
+      of the NOTICE file are for informational purposes only and
+      do not modify the License. You may add Your own attribution
+      notices within Derivative Works that You distribute, alongside
+      or as an addendum to the NOTICE text from the Work, provided
+      that such additional attribution notices cannot be construed
+      as modifying the License.
+
+  You may add Your own copyright statement to Your modifications and
+  may provide additional or different license terms and conditions
+  for use, reproduction, or distribution of Your modifications, or
+  for any such Derivative Works as a whole, provided Your use,
+  reproduction, and distribution of the Work otherwise complies with
+  the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+  any Contribution intentionally submitted for inclusion in the Work
+  by You to the Licensor shall be under the terms and conditions of
+  this License, without any additional terms or conditions.
+  Notwithstanding the above, nothing herein shall supersede or modify
+  the terms of any separate license agreement you may have executed
+  with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+  names, trademarks, service marks, or product names of the Licensor,
+  except as required for reasonable and customary use in describing the
+  origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+  agreed to in writing, Licensor provides the Work (and each
+  Contributor provides its Contributions) on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+  implied, including, without limitation, any warranties or conditions
+  of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+  PARTICULAR PURPOSE. You are solely responsible for determining the
+  appropriateness of using or redistributing the Work and assume any
+  risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+  whether in tort (including negligence), contract, or otherwise,
+  unless required by applicable law (such as deliberate and grossly
+  negligent acts) or agreed to in writing, shall any Contributor be
+  liable to You for damages, including any direct, indirect, special,
+  incidental, or consequential damages of any character arising as a
+  result of this License or out of the use or inability to use the
+  Work (including but not limited to damages for loss of goodwill,
+  work stoppage, computer failure or malfunction, or any and all
+  other commercial damages or losses), even if such Contributor
+  has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+  the Work or Derivative Works thereof, You may choose to offer,
+  and charge a fee for, acceptance of support, warranty, indemnity,
+  or other liability obligations and/or rights consistent with this
+  License. However, in accepting such obligations, You may act only
+  on Your own behalf and on Your sole responsibility, not on behalf
+  of any other Contributor, and only if You agree to indemnify,
+  defend, and hold each Contributor harmless for any liability
+  incurred by, or claims asserted against, such Contributor by reason
+  of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS

+ 63 - 0
vendor/box/spout/README.md

@@ -0,0 +1,63 @@
+# Spout
+
+[![Latest Stable Version](https://poser.pugx.org/box/spout/v/stable)](https://packagist.org/packages/box/spout)
+[![Project Status](https://opensource.box.com/badges/active.svg)](https://opensource.box.com/badges)
+[![Build Status](https://travis-ci.org/box/spout.svg?branch=master)](https://travis-ci.org/box/spout)
+[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/box/spout/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/box/spout/?branch=master)
+[![Code Coverage](https://scrutinizer-ci.com/g/box/spout/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/box/spout/?branch=master)
+[![Total Downloads](https://poser.pugx.org/box/spout/downloads)](https://packagist.org/packages/box/spout)
+
+Spout is a PHP library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way.
+Unlike other file readers or writers, it is capable of processing very large files, while keeping the memory usage really low (less than 3MB).
+
+Join the community and come discuss Spout: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/box/spout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+
+## Documentation
+
+Full documentation can be found at [https://opensource.box.com/spout/](https://opensource.box.com/spout/).
+
+
+## Requirements
+
+* PHP version 7.2 or higher
+* PHP extension `php_zip` enabled
+* PHP extension `php_xmlreader` enabled
+
+## Upgrade guide
+
+Version 3 introduced new functionality but also some breaking changes. If you want to upgrade your Spout codebase from version 2 please consult the [Upgrade guide](UPGRADE-3.0.md). 
+
+## Running tests
+
+The `master` branch includes unit, functional and performance tests.
+If you just want to check that everything is working as expected, executing the unit and functional tests is enough.
+
+* `phpunit` - runs unit and functional tests
+* `phpunit --group perf-tests` - only runs the performance tests
+
+For information, the performance tests take about 10 minutes to run (processing 1 million rows files is not a quick thing).
+
+> Performance tests status: [![Build Status](https://travis-ci.org/box/spout.svg?branch=perf-tests)](https://travis-ci.org/box/spout)
+
+
+## Support
+
+You can ask questions, submit new features ideas or discuss Spout in the chat room:<br>
+[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/box/spout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+## Copyright and License
+
+Copyright 2017 Box, Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

+ 89 - 0
vendor/box/spout/UPGRADE-3.0.md

@@ -0,0 +1,89 @@
+Upgrading from 2.x to 3.0
+=========================
+
+Spout 3.0 introduced several backwards-incompatible changes. The upgrade from Spout 2.x to 3.0 must therefore be done with caution.
+This guide is meant to ease this process.
+
+Most notable changes
+--------------------
+In 2.x, styles were applied per row; it was therefore impossible to apply different styles to cells in the same row.
+With the 3.0 version, this is now possible: each cell can have its own style.
+
+Spout 3.0 tries to enforce better typing. For instance, instead of using/returning generic arrays, Spout now makes use of specific `Row` and `Cell` objects that can encapsulate more data such as type, style, value.
+
+Finally, **_Spout 3.2 only supports PHP 7.2 and above_**, as other PHP versions are no longer supported by the community.
+
+Reader changes
+--------------
+Creating a reader should now be done through the Reader `ReaderEntityFactory`, instead of using the `ReaderFactory`.
+Also, the `ReaderFactory::create($type)` method was removed and replaced by methods for each reader:
+```php
+use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; // namespace is no longer "Box\Spout\Reader"
+...
+$reader = ReaderEntityFactory::createXLSXReader(); // replaces ReaderFactory::create(Type::XLSX)
+$reader = ReaderEntityFactory::createCSVReader();  // replaces ReaderFactory::create(Type::CSV)
+$reader = ReaderEntityFactory::createODSReader();  // replaces ReaderFactory::create(Type::ODS)
+```
+
+When iterating over the spreadsheet rows, Spout now returns `Row` objects, instead of an array containing row values. Accessing the row values should now be done this way:
+```php
+...
+foreach ($reader->getSheetIterator() as $sheet) {
+    foreach ($sheet->getRowIterator() as $row) { // $row is a "Row" object, not an array
+        $rowAsArray = $row->toArray();  // this is the 2.x equivalent
+        // OR
+        $cellsArray = $row->getCells(); // this can be used to get access to cells' details
+        ... 
+    }
+}
+```
+
+Writer changes
+--------------
+Writer creation follows the same change as the reader. It should now be done through the Writer `WriterEntityFactory`, instead of using the `WriterFactory`.
+Also, the `WriterFactory::create($type)` method was removed and replaced by methods for each writer:
+
+```php
+use Box\Spout\Writer\Common\Creator\WriterEntityFactory; // namespace is no longer "Box\Spout\Writer"
+...
+$writer = WriterEntityFactory::createXLSXWriter(); // replaces WriterFactory::create(Type::XLSX)
+$writer = WriterEntityFactory::createCSVWriter();  // replaces WriterFactory::create(Type::CSV)
+$writer = WriterEntityFactory::createODSWriter();  // replaces WriterFactory::create(Type::ODS)
+```
+
+Adding rows is also done differently: instead of passing an array, the writer now takes in a `Row` object (or an array of `Row`). Creating such objects can easily be done this way:
+```php
+// Adding a row from an array of values (2.x equivalent)
+$cellValues = ['foo', 12345];
+$row1 = WriterEntityFactory::createRowFromArray($cellValues, $rowStyle);
+
+// Adding a row from an array of Cell
+$cell1 = WriterEntityFactory::createCell('foo', $cellStyle1); // this cell has its own style
+$cell2 = WriterEntityFactory::createCell(12345, $cellStyle2); // this cell has its own style
+$row2 = WriterEntityFactory::createRow([$cell1, $cell2]);
+
+$writer->addRows([$row1, $row2]);
+```
+
+Namespace changes for styles
+-----------------
+The namespaces for styles have changed. Styles are still created by using a `builder` class.
+
+For the builder, please update your import statements to use the following namespaces:
+
+    Box\Spout\Writer\Common\Creator\Style\StyleBuilder
+    Box\Spout\Writer\Common\Creator\Style\BorderBuilder
+
+The `Style` base class and style definitions like `Border`, `BorderPart` and `Color` also have a new namespace.
+
+If your are using these classes directly via an import statement in your code, please use the following namespaces:
+
+    Box\Spout\Common\Entity\Style\Border
+    Box\Spout\Common\Entity\Style\BorderPart
+    Box\Spout\Common\Entity\Style\Color
+    Box\Spout\Common\Entity\Style\Style
+
+Handling of empty rows
+----------------------
+In 2.x, empty rows were not added to the spreadsheet.
+In 3.0, `addRow` now always writes a row to the spreadsheet: when the row does not contain any cells, an empty row is created in the sheet.

+ 35 - 0
vendor/box/spout/appveyor.yml

@@ -0,0 +1,35 @@
+build: false
+clone_depth: 1
+
+environment:
+  PHP_CHOCO_VERSION: 7.2.0
+  PHP_CACHE_DIR: C:\tools\php
+
+cache:
+  - '%PHP_CACHE_DIR% -> appveyor.yml'
+
+init:
+  - SET PATH=%PHP_CACHE_DIR%;%PATH%
+  - SET COMPOSER_CACHE_DIR=%PHP_CACHE_DIR%
+  - SET COMPOSER_NO_INTERACTION=1
+  - SET PHP=0
+  - SET ANSICON=121x90 (121x90)
+
+install:
+  - IF EXIST %PHP_CACHE_DIR% (SET PHP=1)
+  - IF %PHP%==0 cinst php -y --version %PHP_CHOCO_VERSION%  --params "/InstallDir:%PHP_CACHE_DIR%"
+  - IF %PHP%==0 cinst composer -y --ia "/DEV=%PHP_CACHE_DIR%"
+  - cd %PHP_CACHE_DIR%
+  - IF %PHP%==0 copy php.ini-production php.ini
+  - IF %PHP%==0 echo extension_dir=ext >> php.ini
+  - IF %PHP%==0 echo extension=php_fileinfo.dll >> php.ini
+  - IF %PHP%==0 echo extension=php_mbstring.dll >> php.ini
+  - IF %PHP%==0 echo extension=php_openssl.dll >> php.ini
+  - php -v
+  - IF %PHP%==0 (composer --version) ELSE (composer self-update)
+  - cd %APPVEYOR_BUILD_FOLDER%
+  - composer install --prefer-dist --no-progress
+
+test_script:
+  - cd %APPVEYOR_BUILD_FOLDER%
+  - vendor\bin\phpunit --colors=always

+ 43 - 0
vendor/box/spout/composer.json

@@ -0,0 +1,43 @@
+{
+    "name": "box/spout",
+    "description": "PHP Library to read and write spreadsheet files (CSV, XLSX and ODS), in a fast and scalable way",
+    "type": "library",
+    "keywords": ["php","read","write","csv","xlsx","ods","odf","open","office","excel","spreadsheet","scale","memory","stream","ooxml"],
+    "license": "Apache-2.0",
+    "homepage": "https://www.github.com/box/spout",
+    "authors": [
+        {
+            "name": "Adrien Loison",
+            "email": "adrien@box.com"
+        }
+    ],
+    "require": {
+        "php": ">=7.2.0",
+        "ext-zip": "*",
+        "ext-xmlreader": "*",
+        "ext-dom": "*"
+    },
+    "require-dev": {
+        "phpunit/phpunit": "^8",
+        "friendsofphp/php-cs-fixer": "^2"
+    },
+    "suggest": {
+        "ext-iconv": "To handle non UTF-8 CSV files (if \"php-intl\" is not already installed or is too limited)",
+        "ext-intl": "To handle non UTF-8 CSV files (if \"iconv\" is not already installed)"
+    },
+    "autoload": {
+        "psr-4": {
+            "Box\\Spout\\": "src/Spout"
+        }
+    },
+    "extra": {
+        "branch-alias": {
+            "dev-master": "3.1.x-dev"
+        }
+    },
+    "config": {
+        "platform": {
+            "php": "7.2"
+        }
+    }
+}

+ 148 - 0
vendor/box/spout/src/Spout/Autoloader/Psr4Autoloader.php

@@ -0,0 +1,148 @@
+<?php
+
+namespace Box\Spout\Autoloader;
+
+/**
+ * Class Psr4Autoloader
+ * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader-examples.md#class-example
+ */
+class Psr4Autoloader
+{
+    /**
+     * An associative array where the key is a namespace prefix and the value
+     * is an array of base directories for classes in that namespace.
+     *
+     * @var array
+     */
+    protected $prefixes = [];
+
+    /**
+     * Register loader with SPL autoloader stack.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        \spl_autoload_register([$this, 'loadClass']);
+    }
+
+    /**
+     * Adds a base directory for a namespace prefix.
+     *
+     * @param string $prefix The namespace prefix.
+     * @param string $baseDir A base directory for class files in the
+     * namespace.
+     * @param bool $prepend If true, prepend the base directory to the stack
+     * instead of appending it; this causes it to be searched first rather
+     * than last.
+     * @return void
+     */
+    public function addNamespace($prefix, $baseDir, $prepend = false)
+    {
+        // normalize namespace prefix
+        $prefix = \trim($prefix, '\\') . '\\';
+
+        // normalize the base directory with a trailing separator
+        $baseDir = \rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
+
+        // initialize the namespace prefix array
+        if (isset($this->prefixes[$prefix]) === false) {
+            $this->prefixes[$prefix] = [];
+        }
+
+        // retain the base directory for the namespace prefix
+        if ($prepend) {
+            \array_unshift($this->prefixes[$prefix], $baseDir);
+        } else {
+            \array_push($this->prefixes[$prefix], $baseDir);
+        }
+    }
+
+    /**
+     * Loads the class file for a given class name.
+     *
+     * @param string $class The fully-qualified class name.
+     * @return mixed The mapped file name on success, or boolean false on
+     * failure.
+     */
+    public function loadClass($class)
+    {
+        // the current namespace prefix
+        $prefix = $class;
+
+        // work backwards through the namespace names of the fully-qualified
+        // class name to find a mapped file name
+        while (($pos = \strrpos($prefix, '\\')) !== false) {
+            // retain the trailing namespace separator in the prefix
+            $prefix = \substr($class, 0, $pos + 1);
+
+            // the rest is the relative class name
+            $relativeClass = \substr($class, $pos + 1);
+
+            // try to load a mapped file for the prefix and relative class
+            $mappedFile = $this->loadMappedFile($prefix, $relativeClass);
+            if ($mappedFile !== false) {
+                return $mappedFile;
+            }
+
+            // remove the trailing namespace separator for the next iteration
+            // of strrpos()
+            $prefix = \rtrim($prefix, '\\');
+        }
+
+        // never found a mapped file
+        return false;
+    }
+
+    /**
+     * Load the mapped file for a namespace prefix and relative class.
+     *
+     * @param string $prefix The namespace prefix.
+     * @param string $relativeClass The relative class name.
+     * @return mixed Boolean false if no mapped file can be loaded, or the
+     * name of the mapped file that was loaded.
+     */
+    protected function loadMappedFile($prefix, $relativeClass)
+    {
+        // are there any base directories for this namespace prefix?
+        if (isset($this->prefixes[$prefix]) === false) {
+            return false;
+        }
+
+        // look through base directories for this namespace prefix
+        foreach ($this->prefixes[$prefix] as $baseDir) {
+            // replace the namespace prefix with the base directory,
+            // replace namespace separators with directory separators
+            // in the relative class name, append with .php
+            $file = $baseDir
+                  . \str_replace('\\', '/', $relativeClass)
+                  . '.php';
+
+            // if the mapped file exists, require it
+            if ($this->requireFile($file)) {
+                // yes, we're done
+                return $file;
+            }
+        }
+
+        // never found it
+        return false;
+    }
+
+    /**
+     * If a file exists, require it from the file system.
+     *
+     * @param string $file The file to require.
+     * @return bool True if the file exists, false if not.
+     */
+    protected function requireFile($file)
+    {
+        if (\file_exists($file)) {
+            require $file;
+
+            return true;
+        }
+
+        return false;
+    }
+}

+ 15 - 0
vendor/box/spout/src/Spout/Autoloader/autoload.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace Box\Spout\Autoloader;
+
+require_once 'Psr4Autoloader.php';
+
+/**
+ * @var string
+ * Full path to "src/Spout" which is what we want "Box\Spout" to map to.
+ */
+$srcBaseDirectory = \dirname(\dirname(__FILE__));
+
+$loader = new Psr4Autoloader();
+$loader->register();
+$loader->addNamespace('Box\Spout', $srcBaseDirectory);

+ 49 - 0
vendor/box/spout/src/Spout/Common/Creator/HelperFactory.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace Box\Spout\Common\Creator;
+
+use Box\Spout\Common\Helper\EncodingHelper;
+use Box\Spout\Common\Helper\FileSystemHelper;
+use Box\Spout\Common\Helper\GlobalFunctionsHelper;
+use Box\Spout\Common\Helper\StringHelper;
+
+/**
+ * Class HelperFactory
+ * Factory to create helpers
+ */
+class HelperFactory
+{
+    /**
+     * @return GlobalFunctionsHelper
+     */
+    public function createGlobalFunctionsHelper()
+    {
+        return new GlobalFunctionsHelper();
+    }
+
+    /**
+     * @param string $baseFolderPath The path of the base folder where all the I/O can occur
+     * @return FileSystemHelper
+     */
+    public function createFileSystemHelper($baseFolderPath)
+    {
+        return new FileSystemHelper($baseFolderPath);
+    }
+
+    /**
+     * @param GlobalFunctionsHelper $globalFunctionsHelper
+     * @return EncodingHelper
+     */
+    public function createEncodingHelper(GlobalFunctionsHelper $globalFunctionsHelper)
+    {
+        return new EncodingHelper($globalFunctionsHelper);
+    }
+
+    /**
+     * @return StringHelper
+     */
+    public function createStringHelper()
+    {
+        return new StringHelper();
+    }
+}

+ 216 - 0
vendor/box/spout/src/Spout/Common/Entity/Cell.php

@@ -0,0 +1,216 @@
+<?php
+
+namespace Box\Spout\Common\Entity;
+
+use Box\Spout\Common\Entity\Style\Style;
+use Box\Spout\Common\Helper\CellTypeHelper;
+
+/**
+ * Class Cell
+ */
+class Cell
+{
+    /**
+     * Numeric cell type (whole numbers, fractional numbers, dates)
+     */
+    const TYPE_NUMERIC = 0;
+
+    /**
+     * String (text) cell type
+     */
+    const TYPE_STRING = 1;
+
+    /**
+     * Formula cell type
+     * Not used at the moment
+     */
+    const TYPE_FORMULA = 2;
+
+    /**
+     * Empty cell type
+     */
+    const TYPE_EMPTY = 3;
+
+    /**
+     * Boolean cell type
+     */
+    const TYPE_BOOLEAN = 4;
+
+    /**
+     * Date cell type
+     */
+    const TYPE_DATE = 5;
+
+    /**
+     * Error cell type
+     */
+    const TYPE_ERROR = 6;
+
+    /**
+     * The value of this cell
+     * @var mixed|null
+     */
+    protected $value;
+
+    /**
+     * The cell type
+     * @var int|null
+     */
+    protected $type;
+
+    /**
+     * The cell style
+     * @var Style
+     */
+    protected $style;
+
+    /**
+     * @param mixed|null $value
+     * @param Style|null $style
+     */
+    public function __construct($value, Style $style = null)
+    {
+        $this->setValue($value);
+        $this->setStyle($style);
+    }
+
+    /**
+     * @param mixed|null $value
+     */
+    public function setValue($value)
+    {
+        $this->value = $value;
+        $this->type = $this->detectType($value);
+    }
+
+    /**
+     * @return mixed|null
+     */
+    public function getValue()
+    {
+        return !$this->isError() ? $this->value : null;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getValueEvenIfError()
+    {
+        return $this->value;
+    }
+
+    /**
+     * @param Style|null $style
+     */
+    public function setStyle($style)
+    {
+        $this->style = $style ?: new Style();
+    }
+
+    /**
+     * @return Style
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * @return int|null
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * @param int $type
+     */
+    public function setType($type)
+    {
+        $this->type = $type;
+    }
+
+    /**
+     * Get the current value type
+     *
+     * @param mixed|null $value
+     * @return int
+     */
+    protected function detectType($value)
+    {
+        if (CellTypeHelper::isBoolean($value)) {
+            return self::TYPE_BOOLEAN;
+        }
+        if (CellTypeHelper::isEmpty($value)) {
+            return self::TYPE_EMPTY;
+        }
+        if (CellTypeHelper::isNumeric($value)) {
+            return self::TYPE_NUMERIC;
+        }
+        if (CellTypeHelper::isDateTimeOrDateInterval($value)) {
+            return self::TYPE_DATE;
+        }
+        if (CellTypeHelper::isNonEmptyString($value)) {
+            return self::TYPE_STRING;
+        }
+
+        return self::TYPE_ERROR;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isBoolean()
+    {
+        return $this->type === self::TYPE_BOOLEAN;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isEmpty()
+    {
+        return $this->type === self::TYPE_EMPTY;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isNumeric()
+    {
+        return $this->type === self::TYPE_NUMERIC;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isString()
+    {
+        return $this->type === self::TYPE_STRING;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isDate()
+    {
+        return $this->type === self::TYPE_DATE;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isError()
+    {
+        return $this->type === self::TYPE_ERROR;
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return (string) $this->getValue();
+    }
+}

+ 129 - 0
vendor/box/spout/src/Spout/Common/Entity/Row.php

@@ -0,0 +1,129 @@
+<?php
+
+namespace Box\Spout\Common\Entity;
+
+use Box\Spout\Common\Entity\Style\Style;
+
+class Row
+{
+    /**
+     * The cells in this row
+     * @var Cell[]
+     */
+    protected $cells = [];
+
+    /**
+     * The row style
+     * @var Style
+     */
+    protected $style;
+
+    /**
+     * Row constructor.
+     * @param Cell[] $cells
+     * @param Style|null $style
+     */
+    public function __construct(array $cells, $style)
+    {
+        $this
+            ->setCells($cells)
+            ->setStyle($style);
+    }
+
+    /**
+     * @return Cell[] $cells
+     */
+    public function getCells()
+    {
+        return $this->cells;
+    }
+
+    /**
+     * @param Cell[] $cells
+     * @return Row
+     */
+    public function setCells(array $cells)
+    {
+        $this->cells = [];
+        foreach ($cells as $cell) {
+            $this->addCell($cell);
+        }
+
+        return $this;
+    }
+
+    /**
+     * @param Cell $cell
+     * @param int $cellIndex
+     * @return Row
+     */
+    public function setCellAtIndex(Cell $cell, $cellIndex)
+    {
+        $this->cells[$cellIndex] = $cell;
+
+        return $this;
+    }
+
+    /**
+     * @param int $cellIndex
+     * @return Cell|null
+     */
+    public function getCellAtIndex($cellIndex)
+    {
+        return $this->cells[$cellIndex] ?? null;
+    }
+
+    /**
+     * @param Cell $cell
+     * @return Row
+     */
+    public function addCell(Cell $cell)
+    {
+        $this->cells[] = $cell;
+
+        return $this;
+    }
+
+    /**
+     * @return int
+     */
+    public function getNumCells()
+    {
+        // When using "setCellAtIndex", it's possible to
+        // have "$this->cells" contain holes.
+        if (empty($this->cells)) {
+            return 0;
+        }
+
+        return \max(\array_keys($this->cells)) + 1;
+    }
+
+    /**
+     * @return Style
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * @param Style|null $style
+     * @return Row
+     */
+    public function setStyle($style)
+    {
+        $this->style = $style ?: new Style();
+
+        return $this;
+    }
+
+    /**
+     * @return array The row values, as array
+     */
+    public function toArray()
+    {
+        return \array_map(function (Cell $cell) {
+            return $cell->getValue();
+        }, $this->cells);
+    }
+}

+ 85 - 0
vendor/box/spout/src/Spout/Common/Entity/Style/Border.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace Box\Spout\Common\Entity\Style;
+
+/**
+ * Class Border
+ */
+class Border
+{
+    const LEFT = 'left';
+    const RIGHT = 'right';
+    const TOP = 'top';
+    const BOTTOM = 'bottom';
+
+    const STYLE_NONE = 'none';
+    const STYLE_SOLID = 'solid';
+    const STYLE_DASHED = 'dashed';
+    const STYLE_DOTTED = 'dotted';
+    const STYLE_DOUBLE = 'double';
+
+    const WIDTH_THIN = 'thin';
+    const WIDTH_MEDIUM = 'medium';
+    const WIDTH_THICK = 'thick';
+
+    /** @var array A list of BorderPart objects for this border. */
+    private $parts = [];
+
+    /**
+     * @param array $borderParts
+     */
+    public function __construct(array $borderParts = [])
+    {
+        $this->setParts($borderParts);
+    }
+
+    /**
+     * @param string $name The name of the border part
+     * @return BorderPart|null
+     */
+    public function getPart($name)
+    {
+        return $this->hasPart($name) ? $this->parts[$name] : null;
+    }
+
+    /**
+     * @param string $name The name of the border part
+     * @return bool
+     */
+    public function hasPart($name)
+    {
+        return isset($this->parts[$name]);
+    }
+
+    /**
+     * @return array
+     */
+    public function getParts()
+    {
+        return $this->parts;
+    }
+
+    /**
+     * Set BorderParts
+     * @param array $parts
+     * @return void
+     */
+    public function setParts($parts)
+    {
+        unset($this->parts);
+        foreach ($parts as $part) {
+            $this->addPart($part);
+        }
+    }
+
+    /**
+     * @param BorderPart $borderPart
+     * @return Border
+     */
+    public function addPart(BorderPart $borderPart)
+    {
+        $this->parts[$borderPart->getName()] = $borderPart;
+
+        return $this;
+    }
+}

+ 184 - 0
vendor/box/spout/src/Spout/Common/Entity/Style/BorderPart.php

@@ -0,0 +1,184 @@
+<?php
+
+namespace Box\Spout\Common\Entity\Style;
+
+use Box\Spout\Writer\Exception\Border\InvalidNameException;
+use Box\Spout\Writer\Exception\Border\InvalidStyleException;
+use Box\Spout\Writer\Exception\Border\InvalidWidthException;
+
+/**
+ * Class BorderPart
+ */
+class BorderPart
+{
+    /**
+     * @var string The style of this border part.
+     */
+    protected $style;
+
+    /**
+     * @var string The name of this border part.
+     */
+    protected $name;
+
+    /**
+     * @var string The color of this border part.
+     */
+    protected $color;
+
+    /**
+     * @var string The width of this border part.
+     */
+    protected $width;
+
+    /**
+     * @var array Allowed style constants for parts.
+     */
+    protected static $allowedStyles = [
+        'none',
+        'solid',
+        'dashed',
+        'dotted',
+        'double',
+    ];
+
+    /**
+     * @var array Allowed names constants for border parts.
+     */
+    protected static $allowedNames = [
+        'left',
+        'right',
+        'top',
+        'bottom',
+    ];
+
+    /**
+     * @var array Allowed width constants for border parts.
+     */
+    protected static $allowedWidths = [
+        'thin',
+        'medium',
+        'thick',
+    ];
+
+    /**
+     * @param string $name @see  BorderPart::$allowedNames
+     * @param string $color A RGB color code
+     * @param string $width @see BorderPart::$allowedWidths
+     * @param string $style @see BorderPart::$allowedStyles
+     * @throws InvalidNameException
+     * @throws InvalidStyleException
+     * @throws InvalidWidthException
+     */
+    public function __construct($name, $color = Color::BLACK, $width = Border::WIDTH_MEDIUM, $style = Border::STYLE_SOLID)
+    {
+        $this->setName($name);
+        $this->setColor($color);
+        $this->setWidth($width);
+        $this->setStyle($style);
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * @param string $name The name of the border part @see BorderPart::$allowedNames
+     * @throws InvalidNameException
+     * @return void
+     */
+    public function setName($name)
+    {
+        if (!\in_array($name, self::$allowedNames)) {
+            throw new InvalidNameException($name);
+        }
+        $this->name = $name;
+    }
+
+    /**
+     * @return string
+     */
+    public function getStyle()
+    {
+        return $this->style;
+    }
+
+    /**
+     * @param string $style The style of the border part @see BorderPart::$allowedStyles
+     * @throws InvalidStyleException
+     * @return void
+     */
+    public function setStyle($style)
+    {
+        if (!\in_array($style, self::$allowedStyles)) {
+            throw new InvalidStyleException($style);
+        }
+        $this->style = $style;
+    }
+
+    /**
+     * @return string
+     */
+    public function getColor()
+    {
+        return $this->color;
+    }
+
+    /**
+     * @param string $color The color of the border part @see Color::rgb()
+     * @return void
+     */
+    public function setColor($color)
+    {
+        $this->color = $color;
+    }
+
+    /**
+     * @return string
+     */
+    public function getWidth()
+    {
+        return $this->width;
+    }
+
+    /**
+     * @param string $width The width of the border part @see BorderPart::$allowedWidths
+     * @throws InvalidWidthException
+     * @return void
+     */
+    public function setWidth($width)
+    {
+        if (!\in_array($width, self::$allowedWidths)) {
+            throw new InvalidWidthException($width);
+        }
+        $this->width = $width;
+    }
+
+    /**
+     * @return array
+     */
+    public static function getAllowedStyles()
+    {
+        return self::$allowedStyles;
+    }
+
+    /**
+     * @return array
+     */
+    public static function getAllowedNames()
+    {
+        return self::$allowedNames;
+    }
+
+    /**
+     * @return array
+     */
+    public static function getAllowedWidths()
+    {
+        return self::$allowedWidths;
+    }
+}

+ 32 - 0
vendor/box/spout/src/Spout/Common/Entity/Style/CellAlignment.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace Box\Spout\Common\Entity\Style;
+
+/**
+ * Class Alignment
+ * This class provides constants to work with text alignment.
+ */
+abstract class CellAlignment
+{
+    const LEFT = 'left';
+    const RIGHT = 'right';
+    const CENTER = 'center';
+    const JUSTIFY = 'justify';
+
+    private static $VALID_ALIGNMENTS = [
+        self::LEFT => 1,
+        self::RIGHT => 1,
+        self::CENTER => 1,
+        self::JUSTIFY => 1,
+    ];
+
+    /**
+     * @param string $cellAlignment
+     *
+     * @return bool Whether the given cell alignment is valid
+     */
+    public static function isValid($cellAlignment)
+    {
+        return isset(self::$VALID_ALIGNMENTS[$cellAlignment]);
+    }
+}

+ 84 - 0
vendor/box/spout/src/Spout/Common/Entity/Style/Color.php

@@ -0,0 +1,84 @@
+<?php
+
+namespace Box\Spout\Common\Entity\Style;
+
+use Box\Spout\Common\Exception\InvalidColorException;
+
+/**
+ * Class Color
+ * This class provides constants and functions to work with colors
+ */
+abstract class Color
+{
+    /** Standard colors - based on Office Online */
+    const BLACK = '000000';
+    const WHITE = 'FFFFFF';
+    const RED = 'FF0000';
+    const DARK_RED = 'C00000';
+    const ORANGE = 'FFC000';
+    const YELLOW = 'FFFF00';
+    const LIGHT_GREEN = '92D040';
+    const GREEN = '00B050';
+    const LIGHT_BLUE = '00B0E0';
+    const BLUE = '0070C0';
+    const DARK_BLUE = '002060';
+    const PURPLE = '7030A0';
+
+    /**
+     * Returns an RGB color from R, G and B values
+     *
+     * @param int $red Red component, 0 - 255
+     * @param int $green Green component, 0 - 255
+     * @param int $blue Blue component, 0 - 255
+     * @return string RGB color
+     */
+    public static function rgb($red, $green, $blue)
+    {
+        self::throwIfInvalidColorComponentValue($red);
+        self::throwIfInvalidColorComponentValue($green);
+        self::throwIfInvalidColorComponentValue($blue);
+
+        return \strtoupper(
+            self::convertColorComponentToHex($red) .
+            self::convertColorComponentToHex($green) .
+            self::convertColorComponentToHex($blue)
+        );
+    }
+
+    /**
+     * Throws an exception is the color component value is outside of bounds (0 - 255)
+     *
+     * @param int $colorComponent
+     * @throws \Box\Spout\Common\Exception\InvalidColorException
+     * @return void
+     */
+    protected static function throwIfInvalidColorComponentValue($colorComponent)
+    {
+        if (!\is_int($colorComponent) || $colorComponent < 0 || $colorComponent > 255) {
+            throw new InvalidColorException("The RGB components must be between 0 and 255. Received: $colorComponent");
+        }
+    }
+
+    /**
+     * Converts the color component to its corresponding hexadecimal value
+     *
+     * @param int $colorComponent Color component, 0 - 255
+     * @return string Corresponding hexadecimal value, with a leading 0 if needed. E.g "0f", "2d"
+     */
+    protected static function convertColorComponentToHex($colorComponent)
+    {
+        return \str_pad(\dechex($colorComponent), 2, '0', STR_PAD_LEFT);
+    }
+
+    /**
+     * Returns the ARGB color of the given RGB color,
+     * assuming that alpha value is always 1.
+     *
+     * @param string $rgbColor RGB color like "FF08B2"
+     * @return string ARGB color
+     */
+    public static function toARGB($rgbColor)
+    {
+        return 'FF' . $rgbColor;
+    }
+}

+ 509 - 0
vendor/box/spout/src/Spout/Common/Entity/Style/Style.php

@@ -0,0 +1,509 @@
+<?php
+
+namespace Box\Spout\Common\Entity\Style;
+
+/**
+ * Class Style
+ * Represents a style to be applied to a cell
+ */
+class Style
+{
+    /** Default values */
+    const DEFAULT_FONT_SIZE = 11;
+    const DEFAULT_FONT_COLOR = Color::BLACK;
+    const DEFAULT_FONT_NAME = 'Arial';
+
+    /** @var int|null Style ID */
+    private $id;
+
+    /** @var bool Whether the font should be bold */
+    private $fontBold = false;
+    /** @var bool Whether the bold property was set */
+    private $hasSetFontBold = false;
+
+    /** @var bool Whether the font should be italic */
+    private $fontItalic = false;
+    /** @var bool Whether the italic property was set */
+    private $hasSetFontItalic = false;
+
+    /** @var bool Whether the font should be underlined */
+    private $fontUnderline = false;
+    /** @var bool Whether the underline property was set */
+    private $hasSetFontUnderline = false;
+
+    /** @var bool Whether the font should be struck through */
+    private $fontStrikethrough = false;
+    /** @var bool Whether the strikethrough property was set */
+    private $hasSetFontStrikethrough = false;
+
+    /** @var int Font size */
+    private $fontSize = self::DEFAULT_FONT_SIZE;
+    /** @var bool Whether the font size property was set */
+    private $hasSetFontSize = false;
+
+    /** @var string Font color */
+    private $fontColor = self::DEFAULT_FONT_COLOR;
+    /** @var bool Whether the font color property was set */
+    private $hasSetFontColor = false;
+
+    /** @var string Font name */
+    private $fontName = self::DEFAULT_FONT_NAME;
+    /** @var bool Whether the font name property was set */
+    private $hasSetFontName = false;
+
+    /** @var bool Whether specific font properties should be applied */
+    private $shouldApplyFont = false;
+
+    /** @var bool Whether specific cell alignment should be applied */
+    private $shouldApplyCellAlignment = false;
+    /** @var string Cell alignment */
+    private $cellAlignment;
+    /** @var bool Whether the cell alignment property was set */
+    private $hasSetCellAlignment = false;
+
+    /** @var bool Whether the text should wrap in the cell (useful for long or multi-lines text) */
+    private $shouldWrapText = false;
+    /** @var bool Whether the wrap text property was set */
+    private $hasSetWrapText = false;
+
+    /** @var Border */
+    private $border;
+
+    /** @var bool Whether border properties should be applied */
+    private $shouldApplyBorder = false;
+
+    /** @var string Background color */
+    private $backgroundColor;
+
+    /** @var bool */
+    private $hasSetBackgroundColor = false;
+
+    /** @var string Format */
+    private $format;
+
+    /** @var bool */
+    private $hasSetFormat = false;
+
+    /** @var bool */
+    private $isRegistered = false;
+
+    /** @var bool */
+    private $isEmpty = true;
+
+    /**
+     * @return int|null
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * @param int $id
+     * @return Style
+     */
+    public function setId($id)
+    {
+        $this->id = $id;
+
+        return $this;
+    }
+
+    /**
+     * @return Border
+     */
+    public function getBorder()
+    {
+        return $this->border;
+    }
+
+    /**
+     * @param Border $border
+     * @return Style
+     */
+    public function setBorder(Border $border)
+    {
+        $this->shouldApplyBorder = true;
+        $this->border = $border;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function shouldApplyBorder()
+    {
+        return $this->shouldApplyBorder;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isFontBold()
+    {
+        return $this->fontBold;
+    }
+
+    /**
+     * @return Style
+     */
+    public function setFontBold()
+    {
+        $this->fontBold = true;
+        $this->hasSetFontBold = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontBold()
+    {
+        return $this->hasSetFontBold;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isFontItalic()
+    {
+        return $this->fontItalic;
+    }
+
+    /**
+     * @return Style
+     */
+    public function setFontItalic()
+    {
+        $this->fontItalic = true;
+        $this->hasSetFontItalic = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontItalic()
+    {
+        return $this->hasSetFontItalic;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isFontUnderline()
+    {
+        return $this->fontUnderline;
+    }
+
+    /**
+     * @return Style
+     */
+    public function setFontUnderline()
+    {
+        $this->fontUnderline = true;
+        $this->hasSetFontUnderline = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontUnderline()
+    {
+        return $this->hasSetFontUnderline;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isFontStrikethrough()
+    {
+        return $this->fontStrikethrough;
+    }
+
+    /**
+     * @return Style
+     */
+    public function setFontStrikethrough()
+    {
+        $this->fontStrikethrough = true;
+        $this->hasSetFontStrikethrough = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontStrikethrough()
+    {
+        return $this->hasSetFontStrikethrough;
+    }
+
+    /**
+     * @return int
+     */
+    public function getFontSize()
+    {
+        return $this->fontSize;
+    }
+
+    /**
+     * @param int $fontSize Font size, in pixels
+     * @return Style
+     */
+    public function setFontSize($fontSize)
+    {
+        $this->fontSize = $fontSize;
+        $this->hasSetFontSize = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontSize()
+    {
+        return $this->hasSetFontSize;
+    }
+
+    /**
+     * @return string
+     */
+    public function getFontColor()
+    {
+        return $this->fontColor;
+    }
+
+    /**
+     * Sets the font color.
+     *
+     * @param string $fontColor ARGB color (@see Color)
+     * @return Style
+     */
+    public function setFontColor($fontColor)
+    {
+        $this->fontColor = $fontColor;
+        $this->hasSetFontColor = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontColor()
+    {
+        return $this->hasSetFontColor;
+    }
+
+    /**
+     * @return string
+     */
+    public function getFontName()
+    {
+        return $this->fontName;
+    }
+
+    /**
+     * @param string $fontName Name of the font to use
+     * @return Style
+     */
+    public function setFontName($fontName)
+    {
+        $this->fontName = $fontName;
+        $this->hasSetFontName = true;
+        $this->shouldApplyFont = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetFontName()
+    {
+        return $this->hasSetFontName;
+    }
+
+    /**
+     * @return string
+     */
+    public function getCellAlignment()
+    {
+        return $this->cellAlignment;
+    }
+
+    /**
+     * @param string $cellAlignment The cell alignment
+     *
+     * @return Style
+     */
+    public function setCellAlignment($cellAlignment)
+    {
+        $this->cellAlignment = $cellAlignment;
+        $this->hasSetCellAlignment = true;
+        $this->shouldApplyCellAlignment = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetCellAlignment()
+    {
+        return $this->hasSetCellAlignment;
+    }
+
+    /**
+     * @return bool Whether specific cell alignment should be applied
+     */
+    public function shouldApplyCellAlignment()
+    {
+        return $this->shouldApplyCellAlignment;
+    }
+
+    /**
+     * @return bool
+     */
+    public function shouldWrapText()
+    {
+        return $this->shouldWrapText;
+    }
+
+    /**
+     * @param bool $shouldWrap Should the text be wrapped
+     * @return Style
+     */
+    public function setShouldWrapText($shouldWrap = true)
+    {
+        $this->shouldWrapText = $shouldWrap;
+        $this->hasSetWrapText = true;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function hasSetWrapText()
+    {
+        return $this->hasSetWrapText;
+    }
+
+    /**
+     * @return bool Whether specific font properties should be applied
+     */
+    public function shouldApplyFont()
+    {
+        return $this->shouldApplyFont;
+    }
+
+    /**
+     * Sets the background color
+     * @param string $color ARGB color (@see Color)
+     * @return Style
+     */
+    public function setBackgroundColor($color)
+    {
+        $this->hasSetBackgroundColor = true;
+        $this->backgroundColor = $color;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getBackgroundColor()
+    {
+        return $this->backgroundColor;
+    }
+
+    /**
+     * @return bool Whether the background color should be applied
+     */
+    public function shouldApplyBackgroundColor()
+    {
+        return $this->hasSetBackgroundColor;
+    }
+
+    /**
+     * Sets format
+     * @param string $format
+     * @return Style
+     */
+    public function setFormat($format)
+    {
+        $this->hasSetFormat = true;
+        $this->format = $format;
+        $this->isEmpty = false;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getFormat()
+    {
+        return $this->format;
+    }
+
+    /**
+     * @return bool Whether format should be applied
+     */
+    public function shouldApplyFormat()
+    {
+        return $this->hasSetFormat;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isRegistered() : bool
+    {
+        return $this->isRegistered;
+    }
+
+    public function markAsRegistered(?int $id) : void
+    {
+        $this->setId($id);
+        $this->isRegistered = true;
+    }
+
+    public function unmarkAsRegistered() : void
+    {
+        $this->setId(0);
+        $this->isRegistered = false;
+    }
+
+    public function isEmpty() : bool
+    {
+        return $this->isEmpty;
+    }
+}

+ 10 - 0
vendor/box/spout/src/Spout/Common/Exception/EncodingConversionException.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace Box\Spout\Common\Exception;
+
+/**
+ * Class EncodingConversionException
+ */
+class EncodingConversionException extends SpoutException
+{
+}

+ 10 - 0
vendor/box/spout/src/Spout/Common/Exception/IOException.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace Box\Spout\Common\Exception;
+
+/**
+ * Class IOException
+ */
+class IOException extends SpoutException
+{
+}

+ 10 - 0
vendor/box/spout/src/Spout/Common/Exception/InvalidArgumentException.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace Box\Spout\Common\Exception;
+
+/**
+ * Class InvalidArgumentException
+ */
+class InvalidArgumentException extends SpoutException
+{
+}

+ 10 - 0
vendor/box/spout/src/Spout/Common/Exception/InvalidColorException.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace Box\Spout\Common\Exception;
+
+/**
+ * Class InvalidColorException
+ */
+class InvalidColorException extends SpoutException
+{
+}

+ 12 - 0
vendor/box/spout/src/Spout/Common/Exception/SpoutException.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace Box\Spout\Common\Exception;
+
+/**
+ * Class SpoutException
+ *
+ * @abstract
+ */
+abstract class SpoutException extends \Exception
+{
+}

+ 10 - 0
vendor/box/spout/src/Spout/Common/Exception/UnsupportedTypeException.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace Box\Spout\Common\Exception;
+
+/**
+ * Class UnsupportedTypeException
+ */
+class UnsupportedTypeException extends SpoutException
+{
+}

+ 68 - 0
vendor/box/spout/src/Spout/Common/Helper/CellTypeHelper.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace Box\Spout\Common\Helper;
+
+/**
+ * Class CellTypeHelper
+ * This class provides helper functions to determine the type of the cell value
+ */
+class CellTypeHelper
+{
+    /**
+     * @param $value
+     * @return bool Whether the given value is considered "empty"
+     */
+    public static function isEmpty($value)
+    {
+        return ($value === null || $value === '');
+    }
+
+    /**
+     * @param $value
+     * @return bool Whether the given value is a non empty string
+     */
+    public static function isNonEmptyString($value)
+    {
+        return (\gettype($value) === 'string' && $value !== '');
+    }
+
+    /**
+     * Returns whether the given value is numeric.
+     * A numeric value is from type "integer" or "double" ("float" is not returned by gettype).
+     *
+     * @param $value
+     * @return bool Whether the given value is numeric
+     */
+    public static function isNumeric($value)
+    {
+        $valueType = \gettype($value);
+
+        return ($valueType === 'integer' || $valueType === 'double');
+    }
+
+    /**
+     * Returns whether the given value is boolean.
+     * "true"/"false" and 0/1 are not booleans.
+     *
+     * @param $value
+     * @return bool Whether the given value is boolean
+     */
+    public static function isBoolean($value)
+    {
+        return \gettype($value) === 'boolean';
+    }
+
+    /**
+     * Returns whether the given value is a DateTime or DateInterval object.
+     *
+     * @param $value
+     * @return bool Whether the given value is a DateTime or DateInterval object
+     */
+    public static function isDateTimeOrDateInterval($value)
+    {
+        return (
+            $value instanceof \DateTime ||
+            $value instanceof \DateInterval
+        );
+    }
+}

+ 173 - 0
vendor/box/spout/src/Spout/Common/Helper/EncodingHelper.php

@@ -0,0 +1,173 @@
+<?php
+
+namespace Box\Spout\Common\Helper;
+
+use Box\Spout\Common\Exception\EncodingConversionException;
+
+/**
+ * Class EncodingHelper
+ * This class provides helper functions to work with encodings.
+ */
+class EncodingHelper
+{
+    /** Definition of the encodings that can have a BOM */
+    const ENCODING_UTF8     = 'UTF-8';
+    const ENCODING_UTF16_LE = 'UTF-16LE';
+    const ENCODING_UTF16_BE = 'UTF-16BE';
+    const ENCODING_UTF32_LE = 'UTF-32LE';
+    const ENCODING_UTF32_BE = 'UTF-32BE';
+
+    /** Definition of the BOMs for the different encodings */
+    const BOM_UTF8     = "\xEF\xBB\xBF";
+    const BOM_UTF16_LE = "\xFF\xFE";
+    const BOM_UTF16_BE = "\xFE\xFF";
+    const BOM_UTF32_LE = "\xFF\xFE\x00\x00";
+    const BOM_UTF32_BE = "\x00\x00\xFE\xFF";
+
+    /** @var \Box\Spout\Common\Helper\GlobalFunctionsHelper Helper to work with global functions */
+    protected $globalFunctionsHelper;
+
+    /** @var array Map representing the encodings supporting BOMs (key) and their associated BOM (value) */
+    protected $supportedEncodingsWithBom;
+
+    /**
+     * @param \Box\Spout\Common\Helper\GlobalFunctionsHelper $globalFunctionsHelper
+     */
+    public function __construct($globalFunctionsHelper)
+    {
+        $this->globalFunctionsHelper = $globalFunctionsHelper;
+
+        $this->supportedEncodingsWithBom = [
+            self::ENCODING_UTF8     => self::BOM_UTF8,
+            self::ENCODING_UTF16_LE => self::BOM_UTF16_LE,
+            self::ENCODING_UTF16_BE => self::BOM_UTF16_BE,
+            self::ENCODING_UTF32_LE => self::BOM_UTF32_LE,
+            self::ENCODING_UTF32_BE => self::BOM_UTF32_BE,
+        ];
+    }
+
+    /**
+     * Returns the number of bytes to use as offset in order to skip the BOM.
+     *
+     * @param resource $filePointer Pointer to the file to check
+     * @param string $encoding Encoding of the file to check
+     * @return int Bytes offset to apply to skip the BOM (0 means no BOM)
+     */
+    public function getBytesOffsetToSkipBOM($filePointer, $encoding)
+    {
+        $byteOffsetToSkipBom = 0;
+
+        if ($this->hasBOM($filePointer, $encoding)) {
+            $bomUsed = $this->supportedEncodingsWithBom[$encoding];
+
+            // we skip the N first bytes
+            $byteOffsetToSkipBom = \strlen($bomUsed);
+        }
+
+        return $byteOffsetToSkipBom;
+    }
+
+    /**
+     * Returns whether the file identified by the given pointer has a BOM.
+     *
+     * @param resource $filePointer Pointer to the file to check
+     * @param string $encoding Encoding of the file to check
+     * @return bool TRUE if the file has a BOM, FALSE otherwise
+     */
+    protected function hasBOM($filePointer, $encoding)
+    {
+        $hasBOM = false;
+
+        $this->globalFunctionsHelper->rewind($filePointer);
+
+        if (\array_key_exists($encoding, $this->supportedEncodingsWithBom)) {
+            $potentialBom = $this->supportedEncodingsWithBom[$encoding];
+            $numBytesInBom = \strlen($potentialBom);
+
+            $hasBOM = ($this->globalFunctionsHelper->fgets($filePointer, $numBytesInBom + 1) === $potentialBom);
+        }
+
+        return $hasBOM;
+    }
+
+    /**
+     * Attempts to convert a non UTF-8 string into UTF-8.
+     *
+     * @param string $string Non UTF-8 string to be converted
+     * @param string $sourceEncoding The encoding used to encode the source string
+     * @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed
+     * @return string The converted, UTF-8 string
+     */
+    public function attemptConversionToUTF8($string, $sourceEncoding)
+    {
+        return $this->attemptConversion($string, $sourceEncoding, self::ENCODING_UTF8);
+    }
+
+    /**
+     * Attempts to convert a UTF-8 string into the given encoding.
+     *
+     * @param string $string UTF-8 string to be converted
+     * @param string $targetEncoding The encoding the string should be re-encoded into
+     * @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed
+     * @return string The converted string, encoded with the given encoding
+     */
+    public function attemptConversionFromUTF8($string, $targetEncoding)
+    {
+        return $this->attemptConversion($string, self::ENCODING_UTF8, $targetEncoding);
+    }
+
+    /**
+     * Attempts to convert the given string to the given encoding.
+     * Depending on what is installed on the server, we will try to iconv or mbstring.
+     *
+     * @param string $string string to be converted
+     * @param string $sourceEncoding The encoding used to encode the source string
+     * @param string $targetEncoding The encoding the string should be re-encoded into
+     * @throws \Box\Spout\Common\Exception\EncodingConversionException If conversion is not supported or if the conversion failed
+     * @return string The converted string, encoded with the given encoding
+     */
+    protected function attemptConversion($string, $sourceEncoding, $targetEncoding)
+    {
+        // if source and target encodings are the same, it's a no-op
+        if ($sourceEncoding === $targetEncoding) {
+            return $string;
+        }
+
+        $convertedString = null;
+
+        if ($this->canUseIconv()) {
+            $convertedString = $this->globalFunctionsHelper->iconv($string, $sourceEncoding, $targetEncoding);
+        } elseif ($this->canUseMbString()) {
+            $convertedString = $this->globalFunctionsHelper->mb_convert_encoding($string, $sourceEncoding, $targetEncoding);
+        } else {
+            throw new EncodingConversionException("The conversion from $sourceEncoding to $targetEncoding is not supported. Please install \"iconv\" or \"PHP Intl\".");
+        }
+
+        if ($convertedString === false) {
+            throw new EncodingConversionException("The conversion from $sourceEncoding to $targetEncoding failed.");
+        }
+
+        return $convertedString;
+    }
+
+    /**
+     * Returns whether "iconv" can be used.
+     *
+     * @return bool TRUE if "iconv" is available and can be used, FALSE otherwise
+     */
+    protected function canUseIconv()
+    {
+        return $this->globalFunctionsHelper->function_exists('iconv');
+    }
+
+    /**
+     * Returns whether "mb_string" functions can be used.
+     * These functions come with the PHP Intl package.
+     *
+     * @return bool TRUE if "mb_string" functions are available and can be used, FALSE otherwise
+     */
+    protected function canUseMbString()
+    {
+        return $this->globalFunctionsHelper->function_exists('mb_convert_encoding');
+    }
+}

+ 36 - 0
vendor/box/spout/src/Spout/Common/Helper/Escaper/CSV.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace Box\Spout\Common\Helper\Escaper;
+
+/**
+ * Class CSV
+ * Provides functions to escape and unescape data for CSV files
+ */
+class CSV implements EscaperInterface
+{
+    /**
+     * Escapes the given string to make it compatible with CSV
+     *
+     * @codeCoverageIgnore
+     *
+     * @param string $string The string to escape
+     * @return string The escaped string
+     */
+    public function escape($string)
+    {
+        return $string;
+    }
+
+    /**
+     * Unescapes the given string to make it compatible with CSV
+     *
+     * @codeCoverageIgnore
+     *
+     * @param string $string The string to unescape
+     * @return string The unescaped string
+     */
+    public function unescape($string)
+    {
+        return $string;
+    }
+}

+ 25 - 0
vendor/box/spout/src/Spout/Common/Helper/Escaper/EscaperInterface.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace Box\Spout\Common\Helper\Escaper;
+
+/**
+ * Interface EscaperInterface
+ */
+interface EscaperInterface
+{
+    /**
+     * Escapes the given string to make it compatible with PHP
+     *
+     * @param string $string The string to escape
+     * @return string The escaped string
+     */
+    public function escape($string);
+
+    /**
+     * Unescapes the given string to make it compatible with PHP
+     *
+     * @param string $string The string to unescape
+     * @return string The unescaped string
+     */
+    public function unescape($string);
+}

+ 59 - 0
vendor/box/spout/src/Spout/Common/Helper/Escaper/ODS.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace Box\Spout\Common\Helper\Escaper;
+
+/**
+ * Class ODS
+ * Provides functions to escape and unescape data for ODS files
+ */
+class ODS implements EscaperInterface
+{
+    /**
+     * Escapes the given string to make it compatible with XLSX
+     *
+     * @param string $string The string to escape
+     * @return string The escaped string
+     */
+    public function escape($string)
+    {
+        // @NOTE: Using ENT_QUOTES as XML entities ('<', '>', '&') as well as
+        //        single/double quotes (for XML attributes) need to be encoded.
+        if (\defined('ENT_DISALLOWED')) {
+            // 'ENT_DISALLOWED' ensures that invalid characters in the given document type are replaced.
+            // Otherwise control characters like a vertical tab "\v" will make the XML document unreadable by the XML processor
+            // @link https://github.com/box/spout/issues/329
+            $replacedString = \htmlspecialchars($string, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8');
+        } else {
+            // We are on hhvm or any other engine that does not support ENT_DISALLOWED.
+            $escapedString =  \htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
+
+            // control characters values are from 0 to 1F (hex values) in the ASCII table
+            // some characters should not be escaped though: "\t", "\r" and "\n".
+            $regexPattern = '[\x00-\x08' .
+                            // skipping "\t" (0x9) and "\n" (0xA)
+                            '\x0B-\x0C' .
+                            // skipping "\r" (0xD)
+                            '\x0E-\x1F]';
+            $replacedString = \preg_replace("/$regexPattern/", '�', $escapedString);
+        }
+
+        return $replacedString;
+    }
+
+    /**
+     * Unescapes the given string to make it compatible with XLSX
+     *
+     * @param string $string The string to unescape
+     * @return string The unescaped string
+     */
+    public function unescape($string)
+    {
+        // ==============
+        // =   WARNING  =
+        // ==============
+        // It is assumed that the given string has already had its XML entities decoded.
+        // This is true if the string is coming from a DOMNode (as DOMNode already decode XML entities on creation).
+        // Therefore there is no need to call "htmlspecialchars_decode()".
+        return $string;
+    }
+}

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác