first commit

This commit is contained in:
2026-03-05 13:07:40 +01:00
commit 64ba0721ee
25709 changed files with 4691006 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<?php
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit55743d547c1e55e064902e9a43db0e45::getLoader();

View File

@@ -0,0 +1 @@
ko_fi: codemasher

View File

@@ -0,0 +1,77 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
# https://github.com/sebastianbergmann/phpunit/blob/master/.github/workflows/ci.yml
on:
- pull_request
- push
name: "Continuous Integration"
jobs:
static-code-analysis:
name: "Static Code Analysis"
runs-on: ubuntu-latest
env:
PHAN_ALLOW_XDEBUG: 0
PHAN_DISABLE_XDEBUG_WARN: 1
steps:
- name: "Checkout"
uses: actions/checkout@v2
- name: "Install PHP"
uses: shivammathur/setup-php@v2
with:
php-version: "7.4"
coverage: none
tools: pecl
extensions: ast, gd, imagick, json, mbstring
- name: "Update dependencies with composer"
run: composer update --no-interaction --no-ansi --no-progress --no-suggest
- name: "Run phan"
run: php vendor/bin/phan
tests:
name: "Unit Tests"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
# - windows-latest
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
steps:
- name: "Checkout"
uses: actions/checkout@v2
- name: "Install PHP with extensions"
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
coverage: pcov
tools: pecl
extensions: gd, imagick, json, mbstring
- name: "Install dependencies with composer"
run: composer update --no-ansi --no-interaction --no-progress --no-suggest
- name: "Run tests with phpunit"
run: php vendor/phpunit/phpunit/phpunit --configuration=phpunit.xml
- name: "Send code coverage report to Codecov.io"
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -0,0 +1,5 @@
filter:
excluded_paths:
- examples/*
- tests/*
- vendor/*

View File

@@ -0,0 +1,24 @@
branches:
only:
- main
- v3.2.x
addons:
apt:
packages:
- imagemagick
language: php
matrix:
include:
- php: 7.2
- php: 7.3
- php: 7.4
before_install:
- pecl channel-update pecl.php.net
- printf "\n" | pecl install imagick
install: travis_retry composer install --no-interaction --prefer-source
script: vendor/bin/phpunit --configuration phpunit.xml --coverage-clover clover.xml
after_script: bash <(curl -s https://codecov.io/bash)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Smiley <smiley@chillerlan.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,36 @@
<?php
/**
* Class MyCustomOutput
*
* @filesource MyCustomOutput.php
* @created 24.12.2017
* @package chillerlan\QRCodeExamples
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\QROutputAbstract;
class MyCustomOutput extends QROutputAbstract{
protected function setModuleValues():void{
// TODO: Implement setModuleValues() method.
}
public function dump(string $file = null){
$output = '';
for($row = 0; $row < $this->moduleCount; $row++){
for($col = 0; $col < $this->moduleCount; $col++){
$output .= (int)$this->matrix->check($col, $row);
}
}
return $output;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* Class QRImageWithLogo
*
* @filesource QRImageWithLogo.php
* @created 18.11.2020
* @package chillerlan\QRCodeExamples
* @author smiley <smiley@chillerlan.net>
* @copyright 2020 smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\{QRCodeOutputException, QRImage};
use function imagecopyresampled, imagecreatefrompng, imagesx, imagesy, is_file, is_readable;
/**
* @property \chillerlan\QRCodeExamples\LogoOptions $options
*/
class QRImageWithLogo extends QRImage{
/**
* @param string|null $file
* @param string|null $logo
*
* @return string
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
public function dump(string $file = null, string $logo = null):string{
// set returnResource to true to skip further processing for now
$this->options->returnResource = true;
// of course you could accept other formats too (such as resource or Imagick)
// i'm not checking for the file type either for simplicity reasons (assuming PNG)
if(!is_file($logo) || !is_readable($logo)){
throw new QRCodeOutputException('invalid logo');
}
$this->matrix->setLogoSpace(
$this->options->logoSpaceWidth,
$this->options->logoSpaceHeight
// not utilizing the position here
);
// there's no need to save the result of dump() into $this->image here
parent::dump($file);
$im = imagecreatefrompng($logo);
// get logo image size
$w = imagesx($im);
$h = imagesy($im);
// set new logo size, leave a border of 1 module (no proportional resize/centering)
$lw = ($this->options->logoSpaceWidth - 2) * $this->options->scale;
$lh = ($this->options->logoSpaceHeight - 2) * $this->options->scale;
// get the qrcode size
$ql = $this->matrix->size() * $this->options->scale;
// scale the logo and copy it over. done!
imagecopyresampled($this->image, $im, ($ql - $lw) / 2, ($ql - $lh) / 2, 0, 0, $lw, $lh, $w, $h);
$imageData = $this->dumpImage();
if($file !== null){
$this->saveToFile($imageData, $file);
}
if($this->options->imageBase64){
$imageData = 'data:image/'.$this->options->outputType.';base64,'.base64_encode($imageData);
}
return $imageData;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Class QRImageWithText
*
* example for additional text
*
* @link https://github.com/chillerlan/php-qrcode/issues/35
*
* @filesource QRImageWithText.php
* @created 22.06.2019
* @package chillerlan\QRCodeExamples
* @author smiley <smiley@chillerlan.net>
* @copyright 2019 smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\Output\QRImage;
use function base64_encode, imagechar, imagecolorallocate, imagecolortransparent, imagecopymerge, imagecreatetruecolor,
imagedestroy, imagefilledrectangle, imagefontwidth, in_array, round, str_split, strlen;
class QRImageWithText extends QRImage{
/**
* @param string|null $file
* @param string|null $text
*
* @return string
*/
public function dump(string $file = null, string $text = null):string{
$this->image = imagecreatetruecolor($this->length, $this->length);
$background = imagecolorallocate($this->image, ...$this->options->imageTransparencyBG);
if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
imagecolortransparent($this->image, $background);
}
imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $background);
foreach($this->matrix->matrix() as $y => $row){
foreach($row as $x => $M_TYPE){
$this->setPixel($x, $y, $this->moduleValues[$M_TYPE]);
}
}
// render text output if a string is given
if($text !== null){
$this->addText($text);
}
$imageData = $this->dumpImage($file);
if((bool)$this->options->imageBase64){
$imageData = 'data:image/'.$this->options->outputType.';base64,'.base64_encode($imageData);
}
return $imageData;
}
/**
* @param string $text
*/
protected function addText(string $text):void{
// save the qrcode image
$qrcode = $this->image;
// options things
$textSize = 3; // see imagefontheight() and imagefontwidth()
$textBG = [200, 200, 200];
$textColor = [50, 50, 50];
$bgWidth = $this->length;
$bgHeight = $bgWidth + 20; // 20px extra space
// create a new image with additional space
$this->image = imagecreatetruecolor($bgWidth, $bgHeight);
$background = imagecolorallocate($this->image, ...$textBG);
// allow transparency
if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
imagecolortransparent($this->image, $background);
}
// fill the background
imagefilledrectangle($this->image, 0, 0, $bgWidth, $bgHeight, $background);
// copy over the qrcode
imagecopymerge($this->image, $qrcode, 0, 0, 0, 0, $this->length, $this->length, 100);
imagedestroy($qrcode);
$fontColor = imagecolorallocate($this->image, ...$textColor);
$w = imagefontwidth($textSize);
$x = round(($bgWidth - strlen($text) * $w) / 2);
// loop through the string and draw the letters
foreach(str_split($text) as $i => $chr){
imagechar($this->image, $textSize, $i * $w + $x, $this->length, $chr, $fontColor);
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
*
* @filesource custom_output.php
* @created 24.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
// invoke the QROutputInterface manually
$options = new QROptions([
'version' => 5,
'eccLevel' => QRCode::ECC_L,
]);
$qrOutputInterface = new MyCustomOutput($options, (new QRCode($options))->getMatrix($data));
var_dump($qrOutputInterface->dump());
// or just
$options = new QROptions([
'version' => 5,
'eccLevel' => QRCode::ECC_L,
'outputType' => QRCode::OUTPUT_CUSTOM,
'outputInterface' => MyCustomOutput::class,
]);
var_dump((new QRCode($options))->render($data));

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -0,0 +1,47 @@
<?php
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__ . '/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_FPDF,
'eccLevel' => QRCode::ECC_L,
'scale' => 5,
'imageBase64' => false,
'moduleValues' => [
// finder
1536 => [0, 63, 255], // dark (true)
6 => [255, 255, 255], // light (false), white is the transparency color and is enabled by default
// alignment
2560 => [255, 0, 255],
10 => [255, 255, 255],
// timing
3072 => [255, 0, 0],
12 => [255, 255, 255],
// format
3584 => [67, 191, 84],
14 => [255, 255, 255],
// version
4096 => [62, 174, 190],
16 => [255, 255, 255],
// data
1024 => [0, 0, 0],
4 => [255, 255, 255],
// darkmodule
512 => [0, 0, 0],
// separator
8 => [255, 255, 255],
// quietzone
18 => [255, 255, 255],
],
]);
\header('Content-type: application/pdf');
echo (new QRCode($options))->render($data);

View File

@@ -0,0 +1,102 @@
<?php
/**
*
* @filesource html.php
* @created 21.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once '../vendor/autoload.php';
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>QRCode test</title>
<style>
body{
margin: 5em;
padding: 0;
}
div.qrcode{
margin: 0;
padding: 0;
}
/* rows */
div.qrcode > div {
margin: 0;
padding: 0;
height: 10px;
}
/* modules */
div.qrcode > div > span {
display: inline-block;
width: 10px;
height: 10px;
}
div.qrcode > div > span {
background-color: #ccc;
}
</style>
</head>
<body>
<div class="qrcode">
<?php
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 5,
'outputType' => QRCode::OUTPUT_MARKUP_HTML,
'eccLevel' => QRCode::ECC_L,
'moduleValues' => [
// finder
1536 => '#A71111', // dark (true)
6 => '#FFBFBF', // light (false)
// alignment
2560 => '#A70364',
10 => '#FFC9C9',
// timing
3072 => '#98005D',
12 => '#FFB8E9',
// format
3584 => '#003804',
14 => '#00FB12',
// version
4096 => '#650098',
16 => '#E0B8FF',
// data
1024 => '#4A6000',
4 => '#ECF9BE',
// darkmodule
512 => '#080063',
// separator
8 => '#AFBFBF',
// quietzone
18 => '#FFFFFF',
],
]);
echo (new QRCode($options))->render($data);
?>
</div>
</body>
</html>

View File

@@ -0,0 +1,60 @@
<?php
/**
*
* @filesource image.php
* @created 24.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
'eccLevel' => QRCode::ECC_L,
'scale' => 5,
'imageBase64' => false,
'moduleValues' => [
// finder
1536 => [0, 63, 255], // dark (true)
6 => [255, 255, 255], // light (false), white is the transparency color and is enabled by default
// alignment
2560 => [255, 0, 255],
10 => [255, 255, 255],
// timing
3072 => [255, 0, 0],
12 => [255, 255, 255],
// format
3584 => [67, 191, 84],
14 => [255, 255, 255],
// version
4096 => [62, 174, 190],
16 => [255, 255, 255],
// data
1024 => [0, 0, 0],
4 => [255, 255, 255],
// darkmodule
512 => [0, 0, 0],
// separator
8 => [255, 255, 255],
// quietzone
18 => [255, 255, 255],
],
]);
header('Content-type: image/png');
echo (new QRCode($options))->render($data);

View File

@@ -0,0 +1,45 @@
<?php
/**
*
* @filesource imageWithLogo.php
* @created 18.11.2020
* @author smiley <smiley@chillerlan.net>
* @copyright 2020 smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
/**
* @property int $logoSpaceWidth
* @property int $logoSpaceHeight
*
* @noinspection PhpIllegalPsrClassPathInspection
*/
class LogoOptions extends QROptions{
// size in QR modules, multiply with QROptions::$scale for pixel size
protected $logoSpaceWidth;
protected $logoSpaceHeight;
}
$options = new LogoOptions;
$options->version = 7;
$options->eccLevel = QRCode::ECC_H;
$options->imageBase64 = false;
$options->logoSpaceWidth = 13;
$options->logoSpaceHeight = 13;
$options->scale = 5;
$options->imageTransparent = false;
header('Content-type: image/png');
$qrOutputInterface = new QRImageWithLogo($options, (new QRCode($options))->getMatrix($data));
// dump the output, with an additional logo
echo $qrOutputInterface->dump(null, __DIR__.'/octocat.png');

View File

@@ -0,0 +1,33 @@
<?php
/**
* example for additional text
* @link https://github.com/chillerlan/php-qrcode/issues/35
*
* @filesource imageWithText.php
* @created 22.06.2019
* @author Smiley <smiley@chillerlan.net>
* @copyright 2019 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
'scale' => 3,
'imageBase64' => false,
]);
header('Content-type: image/png');
$qrOutputInterface = new QRImageWithText($options, (new QRCode($options))->getMatrix($data));
// dump the output, with additional text
echo $qrOutputInterface->dump(null, 'example text');

View File

@@ -0,0 +1,59 @@
<?php
/**
*
* @filesource image.php
* @created 24.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_IMAGICK,
'eccLevel' => QRCode::ECC_L,
'scale' => 5,
'moduleValues' => [
// finder
1536 => '#A71111', // dark (true)
6 => '#FFBFBF', // light (false)
// alignment
2560 => '#A70364',
10 => '#FFC9C9',
// timing
3072 => '#98005D',
12 => '#FFB8E9',
// format
3584 => '#003804',
14 => '#00FB12',
// version
4096 => '#650098',
16 => '#E0B8FF',
// data
1024 => '#4A6000',
4 => '#ECF9BE',
// darkmodule
512 => '#080063',
// separator
8 => '#DDDDDD',
// quietzone
18 => '#DDDDDD',
],
]);
header('Content-type: image/png');
echo (new QRCode($options))->render($data);

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,77 @@
<?php
/**
*
* @filesource svg.php
* @created 21.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$gzip = true;
$options = new QROptions([
'version' => 7,
'outputType' => QRCode::OUTPUT_MARKUP_SVG,
'eccLevel' => QRCode::ECC_L,
'svgViewBoxSize' => 530,
'addQuietzone' => true,
'cssClass' => 'my-css-class',
'svgOpacity' => 1.0,
'svgDefs' => '
<linearGradient id="g2">
<stop offset="0%" stop-color="#39F" />
<stop offset="100%" stop-color="#F3F" />
</linearGradient>
<linearGradient id="g1">
<stop offset="0%" stop-color="#F3F" />
<stop offset="100%" stop-color="#39F" />
</linearGradient>
<style>rect{shape-rendering:crispEdges}</style>',
'moduleValues' => [
// finder
1536 => 'url(#g1)', // dark (true)
6 => '#fff', // light (false)
// alignment
2560 => 'url(#g1)',
10 => '#fff',
// timing
3072 => 'url(#g1)',
12 => '#fff',
// format
3584 => 'url(#g1)',
14 => '#fff',
// version
4096 => 'url(#g1)',
16 => '#fff',
// data
1024 => 'url(#g2)',
4 => '#fff',
// darkmodule
512 => 'url(#g1)',
// separator
8 => '#fff',
// quietzone
18 => '#fff',
],
]);
$qrcode = (new QRCode($options))->render($data);
header('Content-type: image/svg+xml');
if($gzip === true){
header('Vary: Accept-Encoding');
header('Content-Encoding: gzip');
$qrcode = gzencode($qrcode ,9);
}
echo $qrcode;

View File

@@ -0,0 +1,68 @@
<?php
/**
*
* @filesource text.php
* @created 21.12.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodeExamples;
use chillerlan\QRCode\{QRCode, QROptions};
require_once __DIR__.'/../vendor/autoload.php';
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
$options = new QROptions([
'version' => 5,
'outputType' => QRCode::OUTPUT_STRING_TEXT,
'eccLevel' => QRCode::ECC_L,
]);
// <pre> to view it in a browser
echo '<pre style="font-size: 75%; line-height: 1;">'.(new QRCode($options))->render($data).'</pre>';
// custom values
$options = new QROptions([
'version' => 5,
'outputType' => QRCode::OUTPUT_STRING_TEXT,
'eccLevel' => QRCode::ECC_L,
'moduleValues' => [
// finder
1536 => 'A', // dark (true)
6 => 'a', // light (false)
// alignment
2560 => 'B',
10 => 'b',
// timing
3072 => 'C',
12 => 'c',
// format
3584 => 'D',
14 => 'd',
// version
4096 => 'E',
16 => 'e',
// data
1024 => 'F',
4 => 'f',
// darkmodule
512 => 'G',
// separator
8 => 'h',
// quietzone
18 => 'i',
],
]);
// <pre> to view it in a browser
echo '<pre style="font-size: 75%; line-height: 1;">'.(new QRCode($options))->render($data).'</pre>';

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpdoc>
<parser>
<target>public/docs</target>
</parser>
<transformer>
<target>public/docs</target>
</transformer>
<files>
<directory>src</directory>
</files>
<transformations>
<template name="responsive-twig"/>
</transformations>
</phpdoc>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<ruleset name="codemasher/php-qrcode PMD ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>codemasher/php-qrcode PMD ruleset</description>
<exclude-pattern>*/examples/*</exclude-pattern>
<exclude-pattern>*/tests/*</exclude-pattern>
<rule ref="rulesets/cleancode.xml">
<exclude name="BooleanArgumentFlag"/>
</rule>
<rule ref="rulesets/codesize.xml/CyclomaticComplexity">
<priority>1</priority>
<properties>
<property name="maximum" value="200" />
</properties>
</rule>
<rule ref="rulesets/controversial.xml">
<exclude name="CamelCaseMethodName"/>
<exclude name="CamelCasePropertyName"/>
<exclude name="CamelCaseParameterName"/>
<exclude name="CamelCaseVariableName"/>
</rule>
<rule ref="rulesets/design.xml">
</rule>
<rule ref="rulesets/naming.xml">
<exclude name="LongVariable"/>
<exclude name="ShortVariable"/>
</rule>
<rule ref="rulesets/unusedcode.xml">
<exclude name="UnusedFormalParameter"/>
</rule>
</ruleset>

View File

@@ -0,0 +1,163 @@
<!DOCTYPE html>
<html lang="en" >
<head >
<meta charset="UTF-8" >
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title >QR Code Generator</title >
<style >
body{ font-size: 20px; line-height: 1.4em; font-family: "Trebuchet MS", sans-serif; color: #000;}
input, textarea, select{font-family: Consolas, "Liberation Mono", Courier, monospace; font-size: 75%; line-height: 1.25em; border: 1px solid #aaa; }
input:focus, textarea:focus, select:focus{ border: 1px solid #ccc; }
label{ cursor: pointer; }
#qrcode-settings, div#qrcode-output{ text-align: center; }
div#qrcode-output > div {margin: 0;padding: 0;height: 3px;}
div#qrcode-output > div > span {display: inline-block;width: 3px;height: 3px;}
div#qrcode-output > div > span {background-color: lightgrey;}
</style >
</head >
<body >
<form id="qrcode-settings" >
<label for="inputstring" >Input String</label ><br /><textarea name="inputstring" id="inputstring" cols="80" rows="3" autocomplete="off" spellcheck="false"></textarea ><br />
<label for="version" >Version</label >
<input id="version" name="version" class="options" type="number" min="1" max="40" value="5" placeholder="version" />
<label for="maskpattern" >Mask Pattern</label >
<input id="maskpattern" name="maskpattern" class="options" type="number" min="-1" max="7" value="-1" placeholder="mask pattern" />
<label for="ecc" >ECC</label >
<select class="options" id="ecc" name="ecc" >
<option value="L" selected="selected" >L - 7%</option >
<option value="M" >M - 15%</option >
<option value="Q" >Q - 25%</option >
<option value="H" >H - 30%</option >
</select >
<br />
<label for="quietzone" >Quiet Zone
<input id="quietzone" name="quietzone" class="options" type="checkbox" value="true" />
</label >
<label for="quietzonesize" >size</label >
<input id="quietzonesize" name="quietzonesize" class="options" type="number" min="0" max="100" value="4" placeholder="quiet zone" />
<br />
<label for="output_type" >Output</label >
<select class="options" id="output_type" name="output_type" >
<option value="html" >Markup - HTML</option >
<option value="svg" selected="selected" >Markup - SVG</option >
<option value="png">Image - png</option >
<option value="jpg" >Image - jpg</option >
<option value="gif" >Image - gif</option >
<option value="text" >String - text</option >
<option value="json" >String - json</option >
</select >
<label for="scale" >scale</label >
<input id="scale" name="scale" class="options" type="number" min="1" max="10" value="5" placeholder="scale" />
<div>Finder</div>
<label for="m_finder_light" >
<input type="text" id="m_finder_light" name="m_finder_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_finder_dark" >
<input type="text" id="m_finder_dark" name="m_finder_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Alignment</div>
<label for="m_alignment_light" >
<input type="text" id="m_alignment_light" name="m_alignment_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_alignment_dark" >
<input type="text" id="m_alignment_dark" name="m_alignment_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Timing</div>
<label for="m_timing_light" >
<input type="text" id="m_timing_light" name="m_timing_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_timing_dark" >
<input type="text" id="m_timing_dark" name="m_timing_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Format</div>
<label for="m_format_light" >
<input type="text" id="m_format_light" name="m_format_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_format_dark" >
<input type="text" id="m_format_dark" name="m_format_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Version</div>
<label for="m_version_light" >
<input type="text" id="m_version_light" name="m_version_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_version_dark" >
<input type="text" id="m_version_dark" name="m_version_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Data</div>
<label for="m_data_light" >
<input type="text" id="m_data_light" name="m_data_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_data_dark" >
<input type="text" id="m_data_dark" name="m_data_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Dark Module</div>
<label for="m_darkmodule_light" >
<input disabled="disabled" type="text" id="m_darkmodule_light" class="options" value="" autocomplete="off" spellcheck="false" />
</label >
<label for="m_darkmodule_dark" >
<input type="text" id="m_darkmodule_dark" name="m_darkmodule_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<div>Separator</div>
<label for="m_separator_light" >
<input type="text" id="m_separator_light" name="m_separator_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_separator_dark" >
<input disabled="disabled" type="text" id="m_separator_dark" class="options" value="" autocomplete="off" spellcheck="false" />
</label >
<div>Quiet Zone</div>
<label for="m_quietzone_light" >
<input type="text" id="m_quietzone_light" name="m_quietzone_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
</label >
<label for="m_quietzone_dark" >
<input disabled="disabled" type="text" id="m_quietzone_dark" class="options" value="" autocomplete="off" spellcheck="false" />
</label >
<br />
<button type="submit" >generate</button >
</form >
<div id="qrcode-output" ></div >
<div><a href="https://play.google.com/store/apps/details?id=com.google.zxing.client.android" >ZXing Barcode Scanner</a ></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.3/prototype.js" ></script >
<script src="https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.js" ></script >
<script >
((form, output, url) => {
$(form).observe('submit', ev => {
Event.stop(ev);
new Ajax.Request(url, {
method: 'post',
parameters: ev.target.serialize(true),
onUninitialized: $(output).update(),
onLoading: $(output).update('[portlandia_screaming.gif]'),
onFailure: response => $(output).update(response.responseJSON.error),
onSuccess: response => $(output).update(response.responseJSON.qrcode),
});
});
})('qrcode-settings', 'qrcode-output', './qrcode.php');
</script >
</body >
</html >

View File

@@ -0,0 +1,97 @@
<?php
/**
* @filesource qrcode.php
* @created 18.11.2017
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCodePublic;
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
require_once '../vendor/autoload.php';
try{
$moduleValues = [
// finder
1536 => $_POST['m_finder_dark'],
6 => $_POST['m_finder_light'],
// alignment
2560 => $_POST['m_alignment_dark'],
10 => $_POST['m_alignment_light'],
// timing
3072 => $_POST['m_timing_dark'],
12 => $_POST['m_timing_light'],
// format
3584 => $_POST['m_format_dark'],
14 => $_POST['m_format_light'],
// version
4096 => $_POST['m_version_dark'],
16 => $_POST['m_version_light'],
// data
1024 => $_POST['m_data_dark'],
4 => $_POST['m_data_light'],
// darkmodule
512 => $_POST['m_darkmodule_dark'],
// separator
8 => $_POST['m_separator_light'],
// quietzone
18 => $_POST['m_quietzone_light'],
];
$moduleValues = array_map(function($v){
if(preg_match('/[a-f\d]{6}/i', $v) === 1){
return in_array($_POST['output_type'], ['png', 'jpg', 'gif'])
? array_map('hexdec', str_split($v, 2))
: '#'.$v ;
}
return null;
}, $moduleValues);
$ecc = in_array($_POST['ecc'], ['L', 'M', 'Q', 'H'], true) ? $_POST['ecc'] : 'L';
$qro = new QROptions;
$qro->version = (int)$_POST['version'];
$qro->eccLevel = constant('chillerlan\\QRCode\\QRCode::ECC_'.$ecc);
$qro->maskPattern = (int)$_POST['maskpattern'];
$qro->addQuietzone = isset($_POST['quietzone']);
$qro->quietzoneSize = (int)$_POST['quietzonesize'];
$qro->moduleValues = $moduleValues;
$qro->outputType = $_POST['output_type'];
$qro->scale = (int)$_POST['scale'];
$qro->imageTransparent = false;
$qrcode = (new QRCode($qro))->render($_POST['inputstring']);
if(in_array($_POST['output_type'], ['png', 'jpg', 'gif'])){
$qrcode = '<img src="'.$qrcode.'" />';
}
elseif($_POST['output_type'] === 'text'){
$qrcode = '<pre style="font-size: 75%; line-height: 1;">'.$qrcode.'</pre>';
}
elseif($_POST['output_type'] === 'json'){
$qrcode = '<pre style="font-size: 75%; overflow-x: auto;">'.$qrcode.'</pre>';
}
send_response(['qrcode' => $qrcode]);
}
// Pokémon exception handler
catch(\Exception $e){
header('HTTP/1.1 500 Internal Server Error');
send_response(['error' => $e->getMessage()]);
}
/**
* @param array $response
*/
function send_response(array $response){
header('Content-type: application/json;charset=utf-8;');
echo json_encode($response);
exit;
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* Class AlphaNum
*
* @filesource AlphaNum.php
* @created 25.11.2015
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\QRCode;
use function array_search, ord, sprintf;
/**
* Alphanumeric mode: 0 to 9, A to Z, space, $ % * + - . / :
*/
class AlphaNum extends QRDataAbstract{
/**
* @inheritdoc
*/
protected $datamode = QRCode::DATA_ALPHANUM;
/**
* @inheritdoc
*/
protected $lengthBits = [9, 11, 13];
/**
* @inheritdoc
*/
protected function write(string $data):void{
for($i = 0; $i + 1 < $this->strlen; $i += 2){
$this->bitBuffer->put($this->getCharCode($data[$i]) * 45 + $this->getCharCode($data[$i + 1]), 11);
}
if($i < $this->strlen){
$this->bitBuffer->put($this->getCharCode($data[$i]), 6);
}
}
/**
* @param string $chr
*
* @return int
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
protected function getCharCode(string $chr):int{
$i = array_search($chr, $this::ALPHANUM_CHAR_MAP);
if($i !== false){
return $i;
}
throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $chr, ord($chr)));
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Class Byte
*
* @filesource Byte.php
* @created 25.11.2015
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\QRCode;
use function ord;
/**
* Byte mode, ISO-8859-1 or UTF-8
*/
class Byte extends QRDataAbstract{
/**
* @inheritdoc
*/
protected $datamode = QRCode::DATA_BYTE;
/**
* @inheritdoc
*/
protected $lengthBits = [8, 16, 16];
/**
* @inheritdoc
*/
protected function write(string $data):void{
$i = 0;
while($i < $this->strlen){
$this->bitBuffer->put(ord($data[$i]), 8);
$i++;
}
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* Class Kanji
*
* @filesource Kanji.php
* @created 25.11.2015
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\QRCode;
use function mb_strlen, ord, sprintf, strlen;
/**
* Kanji mode: double-byte characters from the Shift JIS character set
*/
class Kanji extends QRDataAbstract{
/**
* @inheritdoc
*/
protected $datamode = QRCode::DATA_KANJI;
/**
* @inheritdoc
*/
protected $lengthBits = [8, 10, 12];
/**
* @inheritdoc
*/
protected function getLength(string $data):int{
return mb_strlen($data, 'SJIS');
}
/**
* @inheritdoc
*/
protected function write(string $data):void{
$len = strlen($data);
for($i = 0; $i + 1 < $len; $i += 2){
$c = ((0xff & ord($data[$i])) << 8) | (0xff & ord($data[$i + 1]));
if(0x8140 <= $c && $c <= 0x9FFC){
$c -= 0x8140;
}
elseif(0xE040 <= $c && $c <= 0xEBBF){
$c -= 0xC140;
}
else{
throw new QRCodeDataException(sprintf('illegal char at %d [%d]', $i + 1, $c));
}
$this->bitBuffer->put((($c >> 8) & 0xff) * 0xC0 + ($c & 0xff), 13);
}
if($i < $len){
throw new QRCodeDataException(sprintf('illegal char at %d', $i + 1));
}
}
}

View File

@@ -0,0 +1,203 @@
<?php
/**
* Class MaskPatternTester
*
* @filesource MaskPatternTester.php
* @created 22.11.2017
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use function abs, call_user_func_array;
/**
* The sole purpose of this class is to receive a QRMatrix object and run the pattern tests on it.
*
* @link http://www.thonky.com/qr-code-tutorial/data-masking
*/
class MaskPatternTester{
/**
* @var \chillerlan\QRCode\Data\QRMatrix
*/
protected $matrix;
/**
* @var int
*/
protected $moduleCount;
/**
* Receives the matrix an sets the module count
*
* @see \chillerlan\QRCode\QROptions::$maskPattern
* @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
* @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
*
* @param \chillerlan\QRCode\Data\QRMatrix $matrix
*/
public function __construct(QRMatrix $matrix){
$this->matrix = $matrix;
$this->moduleCount = $this->matrix->size();
}
/**
* Returns the penalty for the given mask pattern
*
* @see \chillerlan\QRCode\QROptions::$maskPattern
* @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
* @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
*
* @return int
*/
public function testPattern():int{
$penalty = 0;
for($level = 1; $level <= 4; $level++){
$penalty += call_user_func_array([$this, 'testLevel'.$level], [$this->matrix->matrix(true)]);
}
return (int)$penalty;
}
/**
* Checks for each group of five or more same-colored modules in a row (or column)
*
* @return int
*/
protected function testLevel1(array $m):int{
$penalty = 0;
foreach($m as $y => $row){
foreach($row as $x => $val){
$count = 0;
for($ry = -1; $ry <= 1; $ry++){
if($y + $ry < 0 || $this->moduleCount <= $y + $ry){
continue;
}
for($rx = -1; $rx <= 1; $rx++){
if(($ry === 0 && $rx === 0) || (($x + $rx) < 0 || $this->moduleCount <= ($x + $rx))){
continue;
}
if($m[$y + $ry][$x + $rx] === $val){
$count++;
}
}
}
if($count > 5){
$penalty += (3 + $count - 5);
}
}
}
return $penalty;
}
/**
* Checks for each 2x2 area of same-colored modules in the matrix
*
* @return int
*/
protected function testLevel2(array $m):int{
$penalty = 0;
foreach($m as $y => $row){
if($y > ($this->moduleCount - 2)){
break;
}
foreach($row as $x => $val){
if($x > ($this->moduleCount - 2)){
break;
}
if(
$val === $m[$y][$x + 1]
&& $val === $m[$y + 1][$x]
&& $val === $m[$y + 1][$x + 1]
){
$penalty++;
}
}
}
return 3 * $penalty;
}
/**
* Checks if there are patterns that look similar to the finder patterns (1:1:3:1:1 ratio)
*
* @return int
*/
protected function testLevel3(array $m):int{
$penalties = 0;
foreach($m as $y => $row){
foreach($row as $x => $val){
if(
($x + 6) < $this->moduleCount
&& $val
&& !$m[$y][$x + 1]
&& $m[$y][$x + 2]
&& $m[$y][$x + 3]
&& $m[$y][$x + 4]
&& !$m[$y][$x + 5]
&& $m[$y][$x + 6]
){
$penalties++;
}
if(
($y + 6) < $this->moduleCount
&& $val
&& !$m[$y + 1][$x]
&& $m[$y + 2][$x]
&& $m[$y + 3][$x]
&& $m[$y + 4][$x]
&& !$m[$y + 5][$x]
&& $m[$y + 6][$x]
){
$penalties++;
}
}
}
return $penalties * 40;
}
/**
* Checks if more than half of the modules are dark or light, with a larger penalty for a larger difference
*
* @return float
*/
protected function testLevel4(array $m):float{
$count = 0;
foreach($m as $y => $row){
foreach($row as $x => $val){
if($val){
$count++;
}
}
}
return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* Class Number
*
* @filesource Number.php
* @created 26.11.2015
* @package QRCode
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\QRCode;
use function ord, sprintf, substr;
/**
* Numeric mode: decimal digits 0 through 9
*/
class Number extends QRDataAbstract{
/**
* @inheritdoc
*/
protected $datamode = QRCode::DATA_NUMBER;
/**
* @inheritdoc
*/
protected $lengthBits = [10, 12, 14];
/**
* @inheritdoc
*/
protected function write(string $data):void{
$i = 0;
while($i + 2 < $this->strlen){
$this->bitBuffer->put($this->parseInt(substr($data, $i, 3)), 10);
$i += 3;
}
if($i < $this->strlen){
if($this->strlen - $i === 1){
$this->bitBuffer->put($this->parseInt(substr($data, $i, $i + 1)), 4);
}
elseif($this->strlen - $i === 2){
$this->bitBuffer->put($this->parseInt(substr($data, $i, $i + 2)), 7);
}
}
}
/**
* @param string $string
*
* @return int
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
protected function parseInt(string $string):int{
$num = 0;
$len = strlen($string);
for($i = 0; $i < $len; $i++){
$c = ord($string[$i]);
if(!in_array($string[$i], $this::NUMBER_CHAR_MAP, true)){
throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $string[$i], $c));
}
$c = $c - 48; // ord('0')
$num = $num * 10 + $c;
}
return $num;
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Class QRCodeDataException
*
* @filesource QRCodeDataException.php
* @created 09.12.2015
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\QRCodeException;
class QRCodeDataException extends QRCodeException{}

View File

@@ -0,0 +1,351 @@
<?php
/**
* Class QRDataAbstract
*
* @filesource QRDataAbstract.php
* @created 25.11.2015
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\{QRCode, QRCodeException};
use chillerlan\QRCode\Helpers\{BitBuffer, Polynomial};
use chillerlan\Settings\SettingsContainerInterface;
use function array_fill, array_merge, count, max, mb_convert_encoding, mb_detect_encoding, range, sprintf, strlen;
/**
* Processes the binary data and maps it on a matrix which is then being returned
*/
abstract class QRDataAbstract implements QRDataInterface{
/**
* the string byte count
*
* @var int
*/
protected $strlen;
/**
* the current data mode: Num, Alphanum, Kanji, Byte
*
* @var int
*/
protected $datamode;
/**
* mode length bits for the version breakpoints 1-9, 10-26 and 27-40
*
* @var array
*/
protected $lengthBits = [0, 0, 0];
/**
* current QR Code version
*
* @var int
*/
protected $version;
/**
* the raw data that's being passed to QRMatrix::mapData()
*
* @var array
*/
protected $matrixdata;
/**
* ECC temp data
*
* @var array
*/
protected $ecdata;
/**
* ECC temp data
*
* @var array
*/
protected $dcdata;
/**
* @var \chillerlan\QRCode\QROptions
*/
protected $options;
/**
* @var \chillerlan\QRCode\Helpers\BitBuffer
*/
protected $bitBuffer;
/**
* QRDataInterface constructor.
*
* @param \chillerlan\Settings\SettingsContainerInterface $options
* @param string|null $data
*/
public function __construct(SettingsContainerInterface $options, string $data = null){
$this->options = $options;
if($data !== null){
$this->setData($data);
}
}
/**
* @inheritDoc
*/
public function setData(string $data):QRDataInterface{
if($this->datamode === QRCode::DATA_KANJI){
$data = mb_convert_encoding($data, 'SJIS', mb_detect_encoding($data));
}
$this->strlen = $this->getLength($data);
$this->version = $this->options->version === QRCode::VERSION_AUTO
? $this->getMinimumVersion()
: $this->options->version;
$this->matrixdata = $this
->writeBitBuffer($data)
->maskECC()
;
return $this;
}
/**
* @inheritDoc
*/
public function initMatrix(int $maskPattern, bool $test = null):QRMatrix{
return (new QRMatrix($this->version, $this->options->eccLevel))
->setFinderPattern()
->setSeparators()
->setAlignmentPattern()
->setTimingPattern()
->setVersionNumber($test)
->setFormatInfo($maskPattern, $test)
->setDarkModule()
->mapData($this->matrixdata, $maskPattern)
;
}
/**
* returns the length bits for the version breakpoints 1-9, 10-26 and 27-40
*
* @return int
* @throws \chillerlan\QRCode\Data\QRCodeDataException
* @codeCoverageIgnore
*/
protected function getLengthBits():int{
foreach([9, 26, 40] as $key => $breakpoint){
if($this->version <= $breakpoint){
return $this->lengthBits[$key];
}
}
throw new QRCodeDataException(sprintf('invalid version number: %d', $this->version));
}
/**
* returns the byte count of the $data string
*
* @param string $data
*
* @return int
*/
protected function getLength(string $data):int{
return strlen($data);
}
/**
* returns the minimum version number for the given string
*
* @return int
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
protected function getMinimumVersion():int{
$maxlength = 0;
// guess the version number within the given range
foreach(range($this->options->versionMin, $this->options->versionMax) as $version){
$maxlength = $this::MAX_LENGTH[$version][QRCode::DATA_MODES[$this->datamode]][QRCode::ECC_MODES[$this->options->eccLevel]];
if($this->strlen <= $maxlength){
return $version;
}
}
throw new QRCodeDataException(sprintf('data exceeds %d characters', $maxlength));
}
/**
* writes the actual data string to the BitBuffer
*
* @see \chillerlan\QRCode\Data\QRDataAbstract::writeBitBuffer()
*
* @param string $data
*
* @return void
*/
abstract protected function write(string $data):void;
/**
* creates a BitBuffer and writes the string data to it
*
* @param string $data
*
* @return \chillerlan\QRCode\Data\QRDataAbstract
* @throws \chillerlan\QRCode\QRCodeException
*/
protected function writeBitBuffer(string $data):QRDataInterface{
$this->bitBuffer = new BitBuffer;
$MAX_BITS = $this::MAX_BITS[$this->version][QRCode::ECC_MODES[$this->options->eccLevel]];
$this->bitBuffer
->clear()
->put($this->datamode, 4)
->put($this->strlen, $this->getLengthBits())
;
$this->write($data);
// there was an error writing the BitBuffer data, which is... unlikely.
if($this->bitBuffer->length > $MAX_BITS){
throw new QRCodeException(sprintf('code length overflow. (%d > %d bit)', $this->bitBuffer->length, $MAX_BITS)); // @codeCoverageIgnore
}
// end code.
if($this->bitBuffer->length + 4 <= $MAX_BITS){
$this->bitBuffer->put(0, 4);
}
// padding
while($this->bitBuffer->length % 8 !== 0){
$this->bitBuffer->putBit(false);
}
// padding
while(true){
if($this->bitBuffer->length >= $MAX_BITS){
break;
}
$this->bitBuffer->put(0xEC, 8);
if($this->bitBuffer->length >= $MAX_BITS){
break;
}
$this->bitBuffer->put(0x11, 8);
}
return $this;
}
/**
* ECC masking
*
* @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
*
* @return array
*/
protected function maskECC():array{
[$l1, $l2, $b1, $b2] = $this::RSBLOCKS[$this->version][QRCode::ECC_MODES[$this->options->eccLevel]];
$rsBlocks = array_fill(0, $l1, [$b1, $b2]);
$rsCount = $l1 + $l2;
$this->ecdata = array_fill(0, $rsCount, null);
$this->dcdata = $this->ecdata;
if($l2 > 0){
$rsBlocks = array_merge($rsBlocks, array_fill(0, $l2, [$b1 + 1, $b2 + 1]));
}
$totalCodeCount = 0;
$maxDcCount = 0;
$maxEcCount = 0;
$offset = 0;
foreach($rsBlocks as $key => $block){
[$rsBlockTotal, $dcCount] = $block;
$ecCount = $rsBlockTotal - $dcCount;
$maxDcCount = max($maxDcCount, $dcCount);
$maxEcCount = max($maxEcCount, $ecCount);
$this->dcdata[$key] = array_fill(0, $dcCount, null);
foreach($this->dcdata[$key] as $a => $_z){
$this->dcdata[$key][$a] = 0xff & $this->bitBuffer->buffer[$a + $offset];
}
[$num, $add] = $this->poly($key, $ecCount);
foreach($this->ecdata[$key] as $c => $_z){
$modIndex = $c + $add;
$this->ecdata[$key][$c] = $modIndex >= 0 ? $num[$modIndex] : 0;
}
$offset += $dcCount;
$totalCodeCount += $rsBlockTotal;
}
$data = array_fill(0, $totalCodeCount, null);
$index = 0;
$mask = function($arr, $count) use (&$data, &$index, $rsCount){
for($x = 0; $x < $count; $x++){
for($y = 0; $y < $rsCount; $y++){
if($x < count($arr[$y])){
$data[$index] = $arr[$y][$x];
$index++;
}
}
}
};
$mask($this->dcdata, $maxDcCount);
$mask($this->ecdata, $maxEcCount);
return $data;
}
/**
* @param int $key
* @param int $count
*
* @return int[]
*/
protected function poly(int $key, int $count):array{
$rsPoly = new Polynomial;
$modPoly = new Polynomial;
for($i = 0; $i < $count; $i++){
$modPoly->setNum([1, $modPoly->gexp($i)]);
$rsPoly->multiply($modPoly->getNum());
}
$rsPolyCount = count($rsPoly->getNum());
$modPoly
->setNum($this->dcdata[$key], $rsPolyCount - 1)
->mod($rsPoly->getNum())
;
$this->ecdata[$key] = array_fill(0, $rsPolyCount - 1, null);
$num = $modPoly->getNum();
return [
$num,
count($num) - count($this->ecdata[$key]),
];
}
}

View File

@@ -0,0 +1,187 @@
<?php
/**
* Interface QRDataInterface
*
* @filesource QRDataInterface.php
* @created 01.12.2015
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
/**
*
*/
interface QRDataInterface{
const NUMBER_CHAR_MAP = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const ALPHANUM_CHAR_MAP = [
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', ' ', '$', '%', '*',
'+', '-', '.', '/', ':',
];
/**
* @link http://www.qrcode.com/en/about/version.html
*/
const MAX_LENGTH =[
// v => [NUMERIC => [L, M, Q, H ], ALPHANUM => [L, M, Q, H], BINARY => [L, M, Q, H ], KANJI => [L, M, Q, H ]] // modules
1 => [[ 41, 34, 27, 17], [ 25, 20, 16, 10], [ 17, 14, 11, 7], [ 10, 8, 7, 4]], // 21
2 => [[ 77, 63, 48, 34], [ 47, 38, 29, 20], [ 32, 26, 20, 14], [ 20, 16, 12, 8]], // 25
3 => [[ 127, 101, 77, 58], [ 77, 61, 47, 35], [ 53, 42, 32, 24], [ 32, 26, 20, 15]], // 29
4 => [[ 187, 149, 111, 82], [ 114, 90, 67, 50], [ 78, 62, 46, 34], [ 48, 38, 28, 21]], // 33
5 => [[ 255, 202, 144, 106], [ 154, 122, 87, 64], [ 106, 84, 60, 44], [ 65, 52, 37, 27]], // 37
6 => [[ 322, 255, 178, 139], [ 195, 154, 108, 84], [ 134, 106, 74, 58], [ 82, 65, 45, 36]], // 41
7 => [[ 370, 293, 207, 154], [ 224, 178, 125, 93], [ 154, 122, 86, 64], [ 95, 75, 53, 39]], // 45
8 => [[ 461, 365, 259, 202], [ 279, 221, 157, 122], [ 192, 152, 108, 84], [ 118, 93, 66, 52]], // 49
9 => [[ 552, 432, 312, 235], [ 335, 262, 189, 143], [ 230, 180, 130, 98], [ 141, 111, 80, 60]], // 53
10 => [[ 652, 513, 364, 288], [ 395, 311, 221, 174], [ 271, 213, 151, 119], [ 167, 131, 93, 74]], // 57
11 => [[ 772, 604, 427, 331], [ 468, 366, 259, 200], [ 321, 251, 177, 137], [ 198, 155, 109, 85]], // 61
12 => [[ 883, 691, 489, 374], [ 535, 419, 296, 227], [ 367, 287, 203, 155], [ 226, 177, 125, 96]], // 65
13 => [[1022, 796, 580, 427], [ 619, 483, 352, 259], [ 425, 331, 241, 177], [ 262, 204, 149, 109]], // 69 NICE!
14 => [[1101, 871, 621, 468], [ 667, 528, 376, 283], [ 458, 362, 258, 194], [ 282, 223, 159, 120]], // 73
15 => [[1250, 991, 703, 530], [ 758, 600, 426, 321], [ 520, 412, 292, 220], [ 320, 254, 180, 136]], // 77
16 => [[1408, 1082, 775, 602], [ 854, 656, 470, 365], [ 586, 450, 322, 250], [ 361, 277, 198, 154]], // 81
17 => [[1548, 1212, 876, 674], [ 938, 734, 531, 408], [ 644, 504, 364, 280], [ 397, 310, 224, 173]], // 85
18 => [[1725, 1346, 948, 746], [1046, 816, 574, 452], [ 718, 560, 394, 310], [ 442, 345, 243, 191]], // 89
19 => [[1903, 1500, 1063, 813], [1153, 909, 644, 493], [ 792, 624, 442, 338], [ 488, 384, 272, 208]], // 93
20 => [[2061, 1600, 1159, 919], [1249, 970, 702, 557], [ 858, 666, 482, 382], [ 528, 410, 297, 235]], // 97
21 => [[2232, 1708, 1224, 969], [1352, 1035, 742, 587], [ 929, 711, 509, 403], [ 572, 438, 314, 248]], // 101
22 => [[2409, 1872, 1358, 1056], [1460, 1134, 823, 640], [1003, 779, 565, 439], [ 618, 480, 348, 270]], // 105
23 => [[2620, 2059, 1468, 1108], [1588, 1248, 890, 672], [1091, 857, 611, 461], [ 672, 528, 376, 284]], // 109
24 => [[2812, 2188, 1588, 1228], [1704, 1326, 963, 744], [1171, 911, 661, 511], [ 721, 561, 407, 315]], // 113
25 => [[3057, 2395, 1718, 1286], [1853, 1451, 1041, 779], [1273, 997, 715, 535], [ 784, 614, 440, 330]], // 117
26 => [[3283, 2544, 1804, 1425], [1990, 1542, 1094, 864], [1367, 1059, 751, 593], [ 842, 652, 462, 365]], // 121
27 => [[3517, 2701, 1933, 1501], [2132, 1637, 1172, 910], [1465, 1125, 805, 625], [ 902, 692, 496, 385]], // 125
28 => [[3669, 2857, 2085, 1581], [2223, 1732, 1263, 958], [1528, 1190, 868, 658], [ 940, 732, 534, 405]], // 129
29 => [[3909, 3035, 2181, 1677], [2369, 1839, 1322, 1016], [1628, 1264, 908, 698], [1002, 778, 559, 430]], // 133
30 => [[4158, 3289, 2358, 1782], [2520, 1994, 1429, 1080], [1732, 1370, 982, 742], [1066, 843, 604, 457]], // 137
31 => [[4417, 3486, 2473, 1897], [2677, 2113, 1499, 1150], [1840, 1452, 1030, 790], [1132, 894, 634, 486]], // 141
32 => [[4686, 3693, 2670, 2022], [2840, 2238, 1618, 1226], [1952, 1538, 1112, 842], [1201, 947, 684, 518]], // 145
33 => [[4965, 3909, 2805, 2157], [3009, 2369, 1700, 1307], [2068, 1628, 1168, 898], [1273, 1002, 719, 553]], // 149
34 => [[5253, 4134, 2949, 2301], [3183, 2506, 1787, 1394], [2188, 1722, 1228, 958], [1347, 1060, 756, 590]], // 153
35 => [[5529, 4343, 3081, 2361], [3351, 2632, 1867, 1431], [2303, 1809, 1283, 983], [1417, 1113, 790, 605]], // 157
36 => [[5836, 4588, 3244, 2524], [3537, 2780, 1966, 1530], [2431, 1911, 1351, 1051], [1496, 1176, 832, 647]], // 161
37 => [[6153, 4775, 3417, 2625], [3729, 2894, 2071, 1591], [2563, 1989, 1423, 1093], [1577, 1224, 876, 673]], // 165
38 => [[6479, 5039, 3599, 2735], [3927, 3054, 2181, 1658], [2699, 2099, 1499, 1139], [1661, 1292, 923, 701]], // 169
39 => [[6743, 5313, 3791, 2927], [4087, 3220, 2298, 1774], [2809, 2213, 1579, 1219], [1729, 1362, 972, 750]], // 173
40 => [[7089, 5596, 3993, 3057], [4296, 3391, 2420, 1852], [2953, 2331, 1663, 1273], [1817, 1435, 1024, 784]], // 177
];
const MAX_BITS = [
// version => [L, M, Q, H ]
1 => [ 152, 128, 104, 72],
2 => [ 272, 224, 176, 128],
3 => [ 440, 352, 272, 208],
4 => [ 640, 512, 384, 288],
5 => [ 864, 688, 496, 368],
6 => [ 1088, 864, 608, 480],
7 => [ 1248, 992, 704, 528],
8 => [ 1552, 1232, 880, 688],
9 => [ 1856, 1456, 1056, 800],
10 => [ 2192, 1728, 1232, 976],
11 => [ 2592, 2032, 1440, 1120],
12 => [ 2960, 2320, 1648, 1264],
13 => [ 3424, 2672, 1952, 1440],
14 => [ 3688, 2920, 2088, 1576],
15 => [ 4184, 3320, 2360, 1784],
16 => [ 4712, 3624, 2600, 2024],
17 => [ 5176, 4056, 2936, 2264],
18 => [ 5768, 4504, 3176, 2504],
19 => [ 6360, 5016, 3560, 2728],
20 => [ 6888, 5352, 3880, 3080],
21 => [ 7456, 5712, 4096, 3248],
22 => [ 8048, 6256, 4544, 3536],
23 => [ 8752, 6880, 4912, 3712],
24 => [ 9392, 7312, 5312, 4112],
25 => [10208, 8000, 5744, 4304],
26 => [10960, 8496, 6032, 4768],
27 => [11744, 9024, 6464, 5024],
28 => [12248, 9544, 6968, 5288],
29 => [13048, 10136, 7288, 5608],
30 => [13880, 10984, 7880, 5960],
31 => [14744, 11640, 8264, 6344],
32 => [15640, 12328, 8920, 6760],
33 => [16568, 13048, 9368, 7208],
34 => [17528, 13800, 9848, 7688],
35 => [18448, 14496, 10288, 7888],
36 => [19472, 15312, 10832, 8432],
37 => [20528, 15936, 11408, 8768],
38 => [21616, 16816, 12016, 9136],
39 => [22496, 17728, 12656, 9776],
40 => [23648, 18672, 13328, 10208],
];
/**
* @link http://www.thonky.com/qr-code-tutorial/error-correction-table
*/
const RSBLOCKS = [
1 => [[ 1, 0, 26, 19], [ 1, 0, 26, 16], [ 1, 0, 26, 13], [ 1, 0, 26, 9]],
2 => [[ 1, 0, 44, 34], [ 1, 0, 44, 28], [ 1, 0, 44, 22], [ 1, 0, 44, 16]],
3 => [[ 1, 0, 70, 55], [ 1, 0, 70, 44], [ 2, 0, 35, 17], [ 2, 0, 35, 13]],
4 => [[ 1, 0, 100, 80], [ 2, 0, 50, 32], [ 2, 0, 50, 24], [ 4, 0, 25, 9]],
5 => [[ 1, 0, 134, 108], [ 2, 0, 67, 43], [ 2, 2, 33, 15], [ 2, 2, 33, 11]],
6 => [[ 2, 0, 86, 68], [ 4, 0, 43, 27], [ 4, 0, 43, 19], [ 4, 0, 43, 15]],
7 => [[ 2, 0, 98, 78], [ 4, 0, 49, 31], [ 2, 4, 32, 14], [ 4, 1, 39, 13]],
8 => [[ 2, 0, 121, 97], [ 2, 2, 60, 38], [ 4, 2, 40, 18], [ 4, 2, 40, 14]],
9 => [[ 2, 0, 146, 116], [ 3, 2, 58, 36], [ 4, 4, 36, 16], [ 4, 4, 36, 12]],
10 => [[ 2, 2, 86, 68], [ 4, 1, 69, 43], [ 6, 2, 43, 19], [ 6, 2, 43, 15]],
11 => [[ 4, 0, 101, 81], [ 1, 4, 80, 50], [ 4, 4, 50, 22], [ 3, 8, 36, 12]],
12 => [[ 2, 2, 116, 92], [ 6, 2, 58, 36], [ 4, 6, 46, 20], [ 7, 4, 42, 14]],
13 => [[ 4, 0, 133, 107], [ 8, 1, 59, 37], [ 8, 4, 44, 20], [12, 4, 33, 11]],
14 => [[ 3, 1, 145, 115], [ 4, 5, 64, 40], [11, 5, 36, 16], [11, 5, 36, 12]],
15 => [[ 5, 1, 109, 87], [ 5, 5, 65, 41], [ 5, 7, 54, 24], [11, 7, 36, 12]],
16 => [[ 5, 1, 122, 98], [ 7, 3, 73, 45], [15, 2, 43, 19], [ 3, 13, 45, 15]],
17 => [[ 1, 5, 135, 107], [10, 1, 74, 46], [ 1, 15, 50, 22], [ 2, 17, 42, 14]],
18 => [[ 5, 1, 150, 120], [ 9, 4, 69, 43], [17, 1, 50, 22], [ 2, 19, 42, 14]],
19 => [[ 3, 4, 141, 113], [ 3, 11, 70, 44], [17, 4, 47, 21], [ 9, 16, 39, 13]],
20 => [[ 3, 5, 135, 107], [ 3, 13, 67, 41], [15, 5, 54, 24], [15, 10, 43, 15]],
21 => [[ 4, 4, 144, 116], [17, 0, 68, 42], [17, 6, 50, 22], [19, 6, 46, 16]],
22 => [[ 2, 7, 139, 111], [17, 0, 74, 46], [ 7, 16, 54, 24], [34, 0, 37, 13]],
23 => [[ 4, 5, 151, 121], [ 4, 14, 75, 47], [11, 14, 54, 24], [16, 14, 45, 15]],
24 => [[ 6, 4, 147, 117], [ 6, 14, 73, 45], [11, 16, 54, 24], [30, 2, 46, 16]],
25 => [[ 8, 4, 132, 106], [ 8, 13, 75, 47], [ 7, 22, 54, 24], [22, 13, 45, 15]],
26 => [[10, 2, 142, 114], [19, 4, 74, 46], [28, 6, 50, 22], [33, 4, 46, 16]],
27 => [[ 8, 4, 152, 122], [22, 3, 73, 45], [ 8, 26, 53, 23], [12, 28, 45, 15]],
28 => [[ 3, 10, 147, 117], [ 3, 23, 73, 45], [ 4, 31, 54, 24], [11, 31, 45, 15]],
29 => [[ 7, 7, 146, 116], [21, 7, 73, 45], [ 1, 37, 53, 23], [19, 26, 45, 15]],
30 => [[ 5, 10, 145, 115], [19, 10, 75, 47], [15, 25, 54, 24], [23, 25, 45, 15]],
31 => [[13, 3, 145, 115], [ 2, 29, 74, 46], [42, 1, 54, 24], [23, 28, 45, 15]],
32 => [[17, 0, 145, 115], [10, 23, 74, 46], [10, 35, 54, 24], [19, 35, 45, 15]],
33 => [[17, 1, 145, 115], [14, 21, 74, 46], [29, 19, 54, 24], [11, 46, 45, 15]],
34 => [[13, 6, 145, 115], [14, 23, 74, 46], [44, 7, 54, 24], [59, 1, 46, 16]],
35 => [[12, 7, 151, 121], [12, 26, 75, 47], [39, 14, 54, 24], [22, 41, 45, 15]],
36 => [[ 6, 14, 151, 121], [ 6, 34, 75, 47], [46, 10, 54, 24], [ 2, 64, 45, 15]],
37 => [[17, 4, 152, 122], [29, 14, 74, 46], [49, 10, 54, 24], [24, 46, 45, 15]],
38 => [[ 4, 18, 152, 122], [13, 32, 74, 46], [48, 14, 54, 24], [42, 32, 45, 15]],
39 => [[20, 4, 147, 117], [40, 7, 75, 47], [43, 22, 54, 24], [10, 67, 45, 15]],
40 => [[19, 6, 148, 118], [18, 31, 75, 47], [34, 34, 54, 24], [20, 61, 45, 15]],
];
/**
* Sets the data string (internally called by the constructor)
*
* @param string $data
*
* @return \chillerlan\QRCode\Data\QRDataInterface
*/
public function setData(string $data):QRDataInterface;
/**
* returns a fresh matrix object with the data written for the given $maskPattern
*
* @param int $maskPattern
* @param bool|null $test
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function initMatrix(int $maskPattern, bool $test = null):QRMatrix;
}

View File

@@ -0,0 +1,733 @@
<?php
/**
* Class QRMatrix
*
* @filesource QRMatrix.php
* @created 15.11.2017
* @package chillerlan\QRCode\Data
* @author Smiley <smiley@chillerlan.net>
* @copyright 2017 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Data;
use chillerlan\QRCode\QRCode;
use Closure;
use function array_fill, array_key_exists, array_push, array_unshift, count, floor, in_array, max, min, range;
/**
* @link http://www.thonky.com/qr-code-tutorial/format-version-information
*/
class QRMatrix{
public const M_NULL = 0x00;
public const M_DARKMODULE = 0x02;
public const M_DATA = 0x04;
public const M_FINDER = 0x06;
public const M_SEPARATOR = 0x08;
public const M_ALIGNMENT = 0x0a;
public const M_TIMING = 0x0c;
public const M_FORMAT = 0x0e;
public const M_VERSION = 0x10;
public const M_QUIETZONE = 0x12;
public const M_LOGO = 0x14;
public const M_FINDER_DOT = 0x16;
public const M_TEST = 0xff;
/**
* @link http://www.thonky.com/qr-code-tutorial/alignment-pattern-locations
*
* version -> pattern
*/
protected const alignmentPattern = [
1 => [],
2 => [6, 18],
3 => [6, 22],
4 => [6, 26],
5 => [6, 30],
6 => [6, 34],
7 => [6, 22, 38],
8 => [6, 24, 42],
9 => [6, 26, 46],
10 => [6, 28, 50],
11 => [6, 30, 54],
12 => [6, 32, 58],
13 => [6, 34, 62],
14 => [6, 26, 46, 66],
15 => [6, 26, 48, 70],
16 => [6, 26, 50, 74],
17 => [6, 30, 54, 78],
18 => [6, 30, 56, 82],
19 => [6, 30, 58, 86],
20 => [6, 34, 62, 90],
21 => [6, 28, 50, 72, 94],
22 => [6, 26, 50, 74, 98],
23 => [6, 30, 54, 78, 102],
24 => [6, 28, 54, 80, 106],
25 => [6, 32, 58, 84, 110],
26 => [6, 30, 58, 86, 114],
27 => [6, 34, 62, 90, 118],
28 => [6, 26, 50, 74, 98, 122],
29 => [6, 30, 54, 78, 102, 126],
30 => [6, 26, 52, 78, 104, 130],
31 => [6, 30, 56, 82, 108, 134],
32 => [6, 34, 60, 86, 112, 138],
33 => [6, 30, 58, 86, 114, 142],
34 => [6, 34, 62, 90, 118, 146],
35 => [6, 30, 54, 78, 102, 126, 150],
36 => [6, 24, 50, 76, 102, 128, 154],
37 => [6, 28, 54, 80, 106, 132, 158],
38 => [6, 32, 58, 84, 110, 136, 162],
39 => [6, 26, 54, 82, 110, 138, 166],
40 => [6, 30, 58, 86, 114, 142, 170],
];
/**
* @link http://www.thonky.com/qr-code-tutorial/format-version-tables
*
* no version pattern for QR Codes < 7
*/
protected const versionPattern = [
7 => 0b000111110010010100,
8 => 0b001000010110111100,
9 => 0b001001101010011001,
10 => 0b001010010011010011,
11 => 0b001011101111110110,
12 => 0b001100011101100010,
13 => 0b001101100001000111,
14 => 0b001110011000001101,
15 => 0b001111100100101000,
16 => 0b010000101101111000,
17 => 0b010001010001011101,
18 => 0b010010101000010111,
19 => 0b010011010100110010,
20 => 0b010100100110100110,
21 => 0b010101011010000011,
22 => 0b010110100011001001,
23 => 0b010111011111101100,
24 => 0b011000111011000100,
25 => 0b011001000111100001,
26 => 0b011010111110101011,
27 => 0b011011000010001110,
28 => 0b011100110000011010,
29 => 0b011101001100111111,
30 => 0b011110110101110101,
31 => 0b011111001001010000,
32 => 0b100000100111010101,
33 => 0b100001011011110000,
34 => 0b100010100010111010,
35 => 0b100011011110011111,
36 => 0b100100101100001011,
37 => 0b100101010000101110,
38 => 0b100110101001100100,
39 => 0b100111010101000001,
40 => 0b101000110001101001,
];
// ECC level -> mask pattern
protected const formatPattern = [
[ // L
0b111011111000100,
0b111001011110011,
0b111110110101010,
0b111100010011101,
0b110011000101111,
0b110001100011000,
0b110110001000001,
0b110100101110110,
],
[ // M
0b101010000010010,
0b101000100100101,
0b101111001111100,
0b101101101001011,
0b100010111111001,
0b100000011001110,
0b100111110010111,
0b100101010100000,
],
[ // Q
0b011010101011111,
0b011000001101000,
0b011111100110001,
0b011101000000110,
0b010010010110100,
0b010000110000011,
0b010111011011010,
0b010101111101101,
],
[ // H
0b001011010001001,
0b001001110111110,
0b001110011100111,
0b001100111010000,
0b000011101100010,
0b000001001010101,
0b000110100001100,
0b000100000111011,
],
];
/**
* @var int
*/
protected $version;
/**
* @var int
*/
protected $eclevel;
/**
* @var int
*/
protected $maskPattern = QRCode::MASK_PATTERN_AUTO;
/**
* @var int
*/
protected $moduleCount;
/**
* @var mixed[]
*/
protected $matrix;
/**
* QRMatrix constructor.
*
* @param int $version
* @param int $eclevel
*
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function __construct(int $version, int $eclevel){
if(!in_array($version, range(1, 40), true)){
throw new QRCodeDataException('invalid QR Code version');
}
if(!array_key_exists($eclevel, QRCode::ECC_MODES)){
throw new QRCodeDataException('invalid ecc level');
}
$this->version = $version;
$this->eclevel = $eclevel;
$this->moduleCount = $this->version * 4 + 17;
$this->matrix = array_fill(0, $this->moduleCount, array_fill(0, $this->moduleCount, $this::M_NULL));
}
/**
* Returns the data matrix, returns a pure boolean representation if $boolean is set to true
*
* @return int[][]|bool[][]
*/
public function matrix(bool $boolean = false):array{
if(!$boolean){
return $this->matrix;
}
$matrix = [];
foreach($this->matrix as $y => $row){
$matrix[$y] = [];
foreach($row as $x => $val){
$matrix[$y][$x] = ($val >> 8) > 0;
}
}
return $matrix;
}
/**
* @return int
*/
public function version():int{
return $this->version;
}
/**
* @return int
*/
public function eccLevel():int{
return $this->eclevel;
}
/**
* @return int
*/
public function maskPattern():int{
return $this->maskPattern;
}
/**
* Returns the absoulute size of the matrix, including quiet zone (after setting it).
*
* size = version * 4 + 17 [ + 2 * quietzone size]
*
* @return int
*/
public function size():int{
return $this->moduleCount;
}
/**
* Returns the value of the module at position [$x, $y]
*
* @param int $x
* @param int $y
*
* @return int
*/
public function get(int $x, int $y):int{
return $this->matrix[$y][$x];
}
/**
* Sets the $M_TYPE value for the module at position [$x, $y]
*
* true => $M_TYPE << 8
* false => $M_TYPE
*
* @param int $x
* @param int $y
* @param int $M_TYPE
* @param bool $value
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function set(int $x, int $y, bool $value, int $M_TYPE):QRMatrix{
$this->matrix[$y][$x] = $M_TYPE << ($value ? 8 : 0);
return $this;
}
/**
* Checks whether a module is true (dark) or false (light)
*
* true => $value >> 8 === $M_TYPE
* $value >> 8 > 0
*
* false => $value === $M_TYPE
* $value >> 8 === 0
*
* @param int $x
* @param int $y
*
* @return bool
*/
public function check(int $x, int $y):bool{
return $this->matrix[$y][$x] >> 8 > 0;
}
/**
* Sets the "dark module", that is always on the same position 1x1px away from the bottom left finder
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setDarkModule():QRMatrix{
$this->set(8, 4 * $this->version + 9, true, $this::M_DARKMODULE);
return $this;
}
/**
* Draws the 7x7 finder patterns in the corners top left/right and bottom left
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setFinderPattern():QRMatrix{
$pos = [
[0, 0], // top left
[$this->moduleCount - 7, 0], // bottom left
[0, $this->moduleCount - 7], // top right
];
foreach($pos as $c){
for($y = 0; $y < 7; $y++){
for($x = 0; $x < 7; $x++){
// outer (dark) 7*7 square
if($x === 0 || $x === 6 || $y === 0 || $y === 6){
$this->set($c[0] + $y, $c[1] + $x, true, $this::M_FINDER);
}
// inner (light) 5*5 square
elseif($x === 1 || $x === 5 || $y === 1 || $y === 5){
$this->set($c[0] + $y, $c[1] + $x, false, $this::M_FINDER);
}
// 3*3 dot
else{
$this->set($c[0] + $y, $c[1] + $x, true, $this::M_FINDER_DOT);
}
}
}
}
return $this;
}
/**
* Draws the separator lines around the finder patterns
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setSeparators():QRMatrix{
$h = [
[7, 0],
[$this->moduleCount - 8, 0],
[7, $this->moduleCount - 8],
];
$v = [
[7, 7],
[$this->moduleCount - 1, 7],
[7, $this->moduleCount - 8],
];
for($c = 0; $c < 3; $c++){
for($i = 0; $i < 8; $i++){
$this->set($h[$c][0] , $h[$c][1] + $i, false, $this::M_SEPARATOR);
$this->set($v[$c][0] - $i, $v[$c][1] , false, $this::M_SEPARATOR);
}
}
return $this;
}
/**
* Draws the 5x5 alignment patterns
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setAlignmentPattern():QRMatrix{
foreach($this::alignmentPattern[$this->version] as $y){
foreach($this::alignmentPattern[$this->version] as $x){
// skip existing patterns
if($this->matrix[$y][$x] !== $this::M_NULL){
continue;
}
for($ry = -2; $ry <= 2; $ry++){
for($rx = -2; $rx <= 2; $rx++){
$v = ($ry === 0 && $rx === 0) || $ry === 2 || $ry === -2 || $rx === 2 || $rx === -2;
$this->set($x + $rx, $y + $ry, $v, $this::M_ALIGNMENT);
}
}
}
}
return $this;
}
/**
* Draws the timing pattern (h/v checkered line between the finder patterns)
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setTimingPattern():QRMatrix{
foreach(range(8, $this->moduleCount - 8 - 1) as $i){
if($this->matrix[6][$i] !== $this::M_NULL || $this->matrix[$i][6] !== $this::M_NULL){
continue;
}
$v = $i % 2 === 0;
$this->set($i, 6, $v, $this::M_TIMING); // h
$this->set(6, $i, $v, $this::M_TIMING); // v
}
return $this;
}
/**
* Draws the version information, 2x 3x6 pixel
*
* @param bool|null $test
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setVersionNumber(bool $test = null):QRMatrix{
$bits = $this::versionPattern[$this->version] ?? false;
if($bits !== false){
for($i = 0; $i < 18; $i++){
$a = (int)floor($i / 3);
$b = $i % 3 + $this->moduleCount - 8 - 3;
$v = !$test && (($bits >> $i) & 1) === 1;
$this->set($b, $a, $v, $this::M_VERSION); // ne
$this->set($a, $b, $v, $this::M_VERSION); // sw
}
}
return $this;
}
/**
* Draws the format info along the finder patterns
*
* @param int $maskPattern
* @param bool|null $test
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function setFormatInfo(int $maskPattern, bool $test = null):QRMatrix{
$bits = $this::formatPattern[QRCode::ECC_MODES[$this->eclevel]][$maskPattern] ?? 0;
for($i = 0; $i < 15; $i++){
$v = !$test && (($bits >> $i) & 1) === 1;
if($i < 6){
$this->set(8, $i, $v, $this::M_FORMAT);
}
elseif($i < 8){
$this->set(8, $i + 1, $v, $this::M_FORMAT);
}
else{
$this->set(8, $this->moduleCount - 15 + $i, $v, $this::M_FORMAT);
}
if($i < 8){
$this->set($this->moduleCount - $i - 1, 8, $v, $this::M_FORMAT);
}
elseif($i < 9){
$this->set(15 - $i, 8, $v, $this::M_FORMAT);
}
else{
$this->set(15 - $i - 1, 8, $v, $this::M_FORMAT);
}
}
$this->set(8, $this->moduleCount - 8, !$test, $this::M_FORMAT);
return $this;
}
/**
* Draws the "quiet zone" of $size around the matrix
*
* @param int|null $size
*
* @return \chillerlan\QRCode\Data\QRMatrix
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function setQuietZone(int $size = null):QRMatrix{
if($this->matrix[$this->moduleCount - 1][$this->moduleCount - 1] === $this::M_NULL){
throw new QRCodeDataException('use only after writing data');
}
$size = $size !== null
? max(0, min($size, floor($this->moduleCount / 2)))
: 4;
for($y = 0; $y < $this->moduleCount; $y++){
for($i = 0; $i < $size; $i++){
array_unshift($this->matrix[$y], $this::M_QUIETZONE);
array_push($this->matrix[$y], $this::M_QUIETZONE);
}
}
$this->moduleCount += ($size * 2);
$r = array_fill(0, $this->moduleCount, $this::M_QUIETZONE);
for($i = 0; $i < $size; $i++){
array_unshift($this->matrix, $r);
array_push($this->matrix, $r);
}
return $this;
}
/**
* Clears a space of $width * $height in order to add a logo or text.
*
* Additionally, the logo space can be positioned within the QR Code - respecting the main functional patterns -
* using $startX and $startY. If either of these are null, the logo space will be centered in that direction.
* ECC level "H" (30%) is required.
*
* Please note that adding a logo space minimizes the error correction capacity of the QR Code and
* created images may become unreadable, especially when printed with a chance to receive damage.
* Please test thoroughly before using this feature in production.
*
* This method should be called from within an output module (after the matrix has been filled with data).
* Note that there is no restiction on how many times this method could be called on the same matrix instance.
*
* @link https://github.com/chillerlan/php-qrcode/issues/52
*
* @param int $width
* @param int $height
* @param int|null $startX
* @param int|null $startY
*
* @return \chillerlan\QRCode\Data\QRMatrix
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function setLogoSpace(int $width, int $height, int $startX = null, int $startY = null):QRMatrix{
// for logos we operate in ECC H (30%) only
if($this->eclevel !== 0b10){
throw new QRCodeDataException('ECC level "H" required to add logo space');
}
// we need uneven sizes to center the logo space, adjust if needed
if($startX === null && ($width % 2) === 0){
$width++;
}
if($startY === null && ($height % 2) === 0){
$height++;
}
// $this->moduleCount includes the quiet zone (if created), we need the QR size here
$length = $this->version * 4 + 17;
// throw if the logo space exceeds the maximum error correction capacity
if($width * $height > floor($length * $length * 0.2)){
throw new QRCodeDataException('logo space exceeds the maximum error correction capacity');
}
// quiet zone size
$qz = ($this->moduleCount - $length) / 2;
// skip quiet zone and the first 9 rows/columns (finder-, mode-, version- and timing patterns)
$start = $qz + 9;
// skip quiet zone
$end = $this->moduleCount - $qz;
// determine start coordinates
$startX = ($startX !== null ? $startX : ($length - $width) / 2) + $qz;
$startY = ($startY !== null ? $startY : ($length - $height) / 2) + $qz;
// clear the space
foreach($this->matrix as $y => $row){
foreach($row as $x => $val){
// out of bounds, skip
if($x < $start || $y < $start ||$x >= $end || $y >= $end){
continue;
}
// a match
if($x >= $startX && $x < ($startX + $width) && $y >= $startY && $y < ($startY + $height)){
$this->set($x, $y, false, $this::M_LOGO);
}
}
}
return $this;
}
/**
* Maps the binary $data array from QRDataInterface::maskECC() on the matrix, using $maskPattern
*
* @see \chillerlan\QRCode\Data\QRDataAbstract::maskECC()
*
* @param int[] $data
* @param int $maskPattern
*
* @return \chillerlan\QRCode\Data\QRMatrix
*/
public function mapData(array $data, int $maskPattern):QRMatrix{
$this->maskPattern = $maskPattern;
$byteCount = count($data);
$size = $this->moduleCount - 1;
$mask = $this->getMask($this->maskPattern);
for($i = $size, $y = $size, $inc = -1, $byteIndex = 0, $bitIndex = 7; $i > 0; $i -= 2){
if($i === 6){
$i--;
}
while(true){
for($c = 0; $c < 2; $c++){
$x = $i - $c;
if($this->matrix[$y][$x] === $this::M_NULL){
$v = false;
if($byteIndex < $byteCount){
$v = (($data[$byteIndex] >> $bitIndex) & 1) === 1;
}
if($mask($x, $y) === 0){
$v = !$v;
}
$this->matrix[$y][$x] = $this::M_DATA << ($v ? 8 : 0);
$bitIndex--;
if($bitIndex === -1){
$byteIndex++;
$bitIndex = 7;
}
}
}
$y += $inc;
if($y < 0 || $this->moduleCount <= $y){
$y -= $inc;
$inc = -$inc;
break;
}
}
}
return $this;
}
/**
* ISO/IEC 18004:2000 Section 8.8.1
*
* Note that some versions of the QR code standard have had errors in the section about mask patterns.
* The information below has been corrected. (https://www.thonky.com/qr-code-tutorial/mask-patterns)
*
* @see \chillerlan\QRCode\QRMatrix::mapData()
*
* @internal
*
* @param int $maskPattern
*
* @return \Closure
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
protected function getMask(int $maskPattern):Closure{
if((0b111 & $maskPattern) !== $maskPattern){
throw new QRCodeDataException('invalid mask pattern'); // @codeCoverageIgnore
}
return [
0b000 => function($x, $y):int{ return ($x + $y) % 2; },
0b001 => function($x, $y):int{ return $y % 2; },
0b010 => function($x, $y):int{ return $x % 3; },
0b011 => function($x, $y):int{ return ($x + $y) % 3; },
0b100 => function($x, $y):int{ return ((int)($y / 2) + (int)($x / 3)) % 2; },
0b101 => function($x, $y):int{ return (($x * $y) % 2) + (($x * $y) % 3); },
0b110 => function($x, $y):int{ return ((($x * $y) % 2) + (($x * $y) % 3)) % 2; },
0b111 => function($x, $y):int{ return ((($x * $y) % 3) + (($x + $y) % 2)) % 2; },
][$maskPattern];
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* Class BitBuffer
*
* @filesource BitBuffer.php
* @created 25.11.2015
* @package chillerlan\QRCode\Helpers
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Helpers;
use function count, floor;
class BitBuffer{
/**
* @var int[]
*/
public $buffer = [];
/**
* @var int
*/
public $length = 0;
/**
* @return \chillerlan\QRCode\Helpers\BitBuffer
*/
public function clear():BitBuffer{
$this->buffer = [];
$this->length = 0;
return $this;
}
/**
* @param int $num
* @param int $length
*
* @return \chillerlan\QRCode\Helpers\BitBuffer
*/
public function put(int $num, int $length):BitBuffer{
for($i = 0; $i < $length; $i++){
$this->putBit((($num >> ($length - $i - 1)) & 1) === 1);
}
return $this;
}
/**
* @param bool $bit
*
* @return \chillerlan\QRCode\Helpers\BitBuffer
*/
public function putBit(bool $bit):BitBuffer{
$bufIndex = floor($this->length / 8);
if(count($this->buffer) <= $bufIndex){
$this->buffer[] = 0;
}
if($bit === true){
$this->buffer[(int)$bufIndex] |= (0x80 >> ($this->length % 8));
}
$this->length++;
return $this;
}
}

View File

@@ -0,0 +1,184 @@
<?php
/**
* Class Polynomial
*
* @filesource Polynomial.php
* @created 25.11.2015
* @package chillerlan\QRCode\Helpers
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Helpers;
use chillerlan\QRCode\QRCodeException;
use function array_fill, count, sprintf;
/**
* @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
*/
class Polynomial{
/**
* @link http://www.thonky.com/qr-code-tutorial/log-antilog-table
*/
protected const table = [
[ 1, 0], [ 2, 0], [ 4, 1], [ 8, 25], [ 16, 2], [ 32, 50], [ 64, 26], [128, 198],
[ 29, 3], [ 58, 223], [116, 51], [232, 238], [205, 27], [135, 104], [ 19, 199], [ 38, 75],
[ 76, 4], [152, 100], [ 45, 224], [ 90, 14], [180, 52], [117, 141], [234, 239], [201, 129],
[143, 28], [ 3, 193], [ 6, 105], [ 12, 248], [ 24, 200], [ 48, 8], [ 96, 76], [192, 113],
[157, 5], [ 39, 138], [ 78, 101], [156, 47], [ 37, 225], [ 74, 36], [148, 15], [ 53, 33],
[106, 53], [212, 147], [181, 142], [119, 218], [238, 240], [193, 18], [159, 130], [ 35, 69],
[ 70, 29], [140, 181], [ 5, 194], [ 10, 125], [ 20, 106], [ 40, 39], [ 80, 249], [160, 185],
[ 93, 201], [186, 154], [105, 9], [210, 120], [185, 77], [111, 228], [222, 114], [161, 166],
[ 95, 6], [190, 191], [ 97, 139], [194, 98], [153, 102], [ 47, 221], [ 94, 48], [188, 253],
[101, 226], [202, 152], [137, 37], [ 15, 179], [ 30, 16], [ 60, 145], [120, 34], [240, 136],
[253, 54], [231, 208], [211, 148], [187, 206], [107, 143], [214, 150], [177, 219], [127, 189],
[254, 241], [225, 210], [223, 19], [163, 92], [ 91, 131], [182, 56], [113, 70], [226, 64],
[217, 30], [175, 66], [ 67, 182], [134, 163], [ 17, 195], [ 34, 72], [ 68, 126], [136, 110],
[ 13, 107], [ 26, 58], [ 52, 40], [104, 84], [208, 250], [189, 133], [103, 186], [206, 61],
[129, 202], [ 31, 94], [ 62, 155], [124, 159], [248, 10], [237, 21], [199, 121], [147, 43],
[ 59, 78], [118, 212], [236, 229], [197, 172], [151, 115], [ 51, 243], [102, 167], [204, 87],
[133, 7], [ 23, 112], [ 46, 192], [ 92, 247], [184, 140], [109, 128], [218, 99], [169, 13],
[ 79, 103], [158, 74], [ 33, 222], [ 66, 237], [132, 49], [ 21, 197], [ 42, 254], [ 84, 24],
[168, 227], [ 77, 165], [154, 153], [ 41, 119], [ 82, 38], [164, 184], [ 85, 180], [170, 124],
[ 73, 17], [146, 68], [ 57, 146], [114, 217], [228, 35], [213, 32], [183, 137], [115, 46],
[230, 55], [209, 63], [191, 209], [ 99, 91], [198, 149], [145, 188], [ 63, 207], [126, 205],
[252, 144], [229, 135], [215, 151], [179, 178], [123, 220], [246, 252], [241, 190], [255, 97],
[227, 242], [219, 86], [171, 211], [ 75, 171], [150, 20], [ 49, 42], [ 98, 93], [196, 158],
[149, 132], [ 55, 60], [110, 57], [220, 83], [165, 71], [ 87, 109], [174, 65], [ 65, 162],
[130, 31], [ 25, 45], [ 50, 67], [100, 216], [200, 183], [141, 123], [ 7, 164], [ 14, 118],
[ 28, 196], [ 56, 23], [112, 73], [224, 236], [221, 127], [167, 12], [ 83, 111], [166, 246],
[ 81, 108], [162, 161], [ 89, 59], [178, 82], [121, 41], [242, 157], [249, 85], [239, 170],
[195, 251], [155, 96], [ 43, 134], [ 86, 177], [172, 187], [ 69, 204], [138, 62], [ 9, 90],
[ 18, 203], [ 36, 89], [ 72, 95], [144, 176], [ 61, 156], [122, 169], [244, 160], [245, 81],
[247, 11], [243, 245], [251, 22], [235, 235], [203, 122], [139, 117], [ 11, 44], [ 22, 215],
[ 44, 79], [ 88, 174], [176, 213], [125, 233], [250, 230], [233, 231], [207, 173], [131, 232],
[ 27, 116], [ 54, 214], [108, 244], [216, 234], [173, 168], [ 71, 80], [142, 88], [ 1, 175],
];
/**
* @var array
*/
protected $num = [];
/**
* Polynomial constructor.
*
* @param array|null $num
* @param int|null $shift
*/
public function __construct(array $num = null, int $shift = null){
$this->setNum($num ?? [1], $shift);
}
/**
* @return array
*/
public function getNum():array{
return $this->num;
}
/**
* @param array $num
* @param int|null $shift
*
* @return \chillerlan\QRCode\Helpers\Polynomial
*/
public function setNum(array $num, int $shift = null):Polynomial{
$offset = 0;
$numCount = count($num);
while($offset < $numCount && $num[$offset] === 0){
$offset++;
}
$this->num = array_fill(0, $numCount - $offset + ($shift ?? 0), 0);
for($i = 0; $i < $numCount - $offset; $i++){
$this->num[$i] = $num[$i + $offset];
}
return $this;
}
/**
* @param array $e
*
* @return \chillerlan\QRCode\Helpers\Polynomial
*/
public function multiply(array $e):Polynomial{
$n = array_fill(0, count($this->num) + count($e) - 1, 0);
foreach($this->num as $i => $vi){
$vi = $this->glog($vi);
foreach($e as $j => $vj){
$n[$i + $j] ^= $this->gexp($vi + $this->glog($vj));
}
}
$this->setNum($n);
return $this;
}
/**
* @param array $e
*
* @return \chillerlan\QRCode\Helpers\Polynomial
*/
public function mod(array $e):Polynomial{
$n = $this->num;
if(count($n) - count($e) < 0){
return $this;
}
$ratio = $this->glog($n[0]) - $this->glog($e[0]);
foreach($e as $i => $v){
$n[$i] ^= $this->gexp($this->glog($v) + $ratio);
}
$this->setNum($n)->mod($e);
return $this;
}
/**
* @param int $n
*
* @return int
* @throws \chillerlan\QRCode\QRCodeException
*/
public function glog(int $n):int{
if($n < 1){
throw new QRCodeException(sprintf('log(%s)', $n));
}
return Polynomial::table[$n][1];
}
/**
* @param int $n
*
* @return int
*/
public function gexp(int $n):int{
if($n < 0){
$n += 255;
}
elseif($n >= 256){
$n -= 255;
}
return Polynomial::table[$n][0];
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* Class QRCodeOutputException
*
* @filesource QRCodeOutputException.php
* @created 09.12.2015
* @package chillerlan\QRCode\Output
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\QRCodeException;
class QRCodeOutputException extends QRCodeException{}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Class QRFpdf
*
* https://github.com/chillerlan/php-qrcode/pull/49
*
* @filesource QRFpdf.php
* @created 03.06.2020
* @package chillerlan\QRCode\Output
* @author Maximilian Kresse
*
* @license MIT
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\QRCodeException;
use chillerlan\Settings\SettingsContainerInterface;
use FPDF;
use function array_values, class_exists, count, is_array;
/**
* QRFpdf output module (requires fpdf)
*
* @see https://github.com/Setasign/FPDF
* @see http://www.fpdf.org/
*/
class QRFpdf extends QROutputAbstract{
public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
if(!class_exists(FPDF::class)){
// @codeCoverageIgnoreStart
throw new QRCodeException(
'The QRFpdf output requires FPDF as dependency but the class "\FPDF" couldn\'t be found.'
);
// @codeCoverageIgnoreEnd
}
parent::__construct($options, $matrix);
}
/**
* @inheritDoc
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_array($v) || count($v) < 3){
$this->moduleValues[$M_TYPE] = $defaultValue
? [0, 0, 0]
: [255, 255, 255];
}
else{
$this->moduleValues[$M_TYPE] = array_values($v);
}
}
}
/**
* @inheritDoc
*
* @return string|\FPDF
*/
public function dump(string $file = null){
$file = $file ?? $this->options->cachefile;
$fpdf = new FPDF('P', $this->options->fpdfMeasureUnit, [$this->length, $this->length]);
$fpdf->AddPage();
$prevColor = null;
foreach($this->matrix->matrix() as $y => $row){
foreach($row as $x => $M_TYPE){
/** @var int $M_TYPE */
$color = $this->moduleValues[$M_TYPE];
if($prevColor === null || $prevColor !== $color){
$fpdf->SetFillColor(...$color);
$prevColor = $color;
}
$fpdf->Rect($x * $this->scale, $y * $this->scale, 1 * $this->scale, 1 * $this->scale, 'F');
}
}
if($this->options->returnResource){
return $fpdf;
}
$pdfData = $fpdf->Output('S');
if($file !== null){
$this->saveToFile($pdfData, $file);
}
if($this->options->imageBase64){
$pdfData = sprintf('data:application/pdf;base64,%s', base64_encode($pdfData));
}
return $pdfData;
}
}

View File

@@ -0,0 +1,208 @@
<?php
/**
* Class QRImage
*
* @filesource QRImage.php
* @created 05.12.2015
* @package chillerlan\QRCode\Output
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\{QRCode, QRCodeException};
use chillerlan\Settings\SettingsContainerInterface;
use Exception;
use function array_values, base64_encode, call_user_func, count, imagecolorallocate, imagecolortransparent,
imagecreatetruecolor, imagedestroy, imagefilledrectangle, imagegif, imagejpeg, imagepng, in_array,
is_array, ob_end_clean, ob_get_contents, ob_start, range, sprintf;
/**
* Converts the matrix into GD images, raw or base64 output
* requires ext-gd
* @link http://php.net/manual/book.image.php
*/
class QRImage extends QROutputAbstract{
protected const TRANSPARENCY_TYPES = [
QRCode::OUTPUT_IMAGE_PNG,
QRCode::OUTPUT_IMAGE_GIF,
];
/**
* @var string
*/
protected $defaultMode = QRCode::OUTPUT_IMAGE_PNG;
/**
* @see imagecreatetruecolor()
* @var resource
*/
protected $image;
/**
* @inheritDoc
*
* @throws \chillerlan\QRCode\QRCodeException
*/
public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
if(!extension_loaded('gd')){
throw new QRCodeException('ext-gd not loaded'); // @codeCoverageIgnore
}
parent::__construct($options, $matrix);
}
/**
* @inheritDoc
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_array($v) || count($v) < 3){
$this->moduleValues[$M_TYPE] = $defaultValue
? [0, 0, 0]
: [255, 255, 255];
}
else{
$this->moduleValues[$M_TYPE] = array_values($v);
}
}
}
/**
* @inheritDoc
*
* @return string|resource
*/
public function dump(string $file = null){
$this->image = imagecreatetruecolor($this->length, $this->length);
// avoid: Indirect modification of overloaded property $imageTransparencyBG has no effect
// https://stackoverflow.com/a/10455217
$tbg = $this->options->imageTransparencyBG;
$background = imagecolorallocate($this->image, ...$tbg);
if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
imagecolortransparent($this->image, $background);
}
imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $background);
foreach($this->matrix->matrix() as $y => $row){
foreach($row as $x => $M_TYPE){
$this->setPixel($x, $y, $this->moduleValues[$M_TYPE]);
}
}
if($this->options->returnResource){
return $this->image;
}
$imageData = $this->dumpImage($file);
if($this->options->imageBase64){
$imageData = sprintf('data:image/%s;base64,%s', $this->options->outputType, base64_encode($imageData));
}
return $imageData;
}
/**
* @param int $x
* @param int $y
* @param array $rgb
*
* @return void
*/
protected function setPixel(int $x, int $y, array $rgb):void{
imagefilledrectangle(
$this->image,
$x * $this->scale,
$y * $this->scale,
($x + 1) * $this->scale,
($y + 1) * $this->scale,
imagecolorallocate($this->image, ...$rgb)
);
}
/**
* @param string|null $file
*
* @return string
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
protected function dumpImage(string $file = null):string{
$file = $file ?? $this->options->cachefile;
ob_start();
try{
call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
}
// not going to cover edge cases
// @codeCoverageIgnoreStart
catch(Exception $e){
throw new QRCodeOutputException($e->getMessage());
}
// @codeCoverageIgnoreEnd
$imageData = ob_get_contents();
imagedestroy($this->image);
ob_end_clean();
if($file !== null){
$this->saveToFile($imageData, $file);
}
return $imageData;
}
/**
* @return void
*/
protected function png():void{
imagepng(
$this->image,
null,
in_array($this->options->pngCompression, range(-1, 9), true)
? $this->options->pngCompression
: -1
);
}
/**
* Jiff - like... JitHub!
* @return void
*/
protected function gif():void{
imagegif($this->image);
}
/**
* @return void
*/
protected function jpg():void{
imagejpeg(
$this->image,
null,
in_array($this->options->jpegQuality, range(0, 100), true)
? $this->options->jpegQuality
: 85
);
}
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* Class QRImagick
*
* @filesource QRImagick.php
* @created 04.07.2018
* @package chillerlan\QRCode\Output
* @author smiley <smiley@chillerlan.net>
* @copyright 2018 smiley
* @license MIT
*
* @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\QRCode\QRCodeException;
use chillerlan\Settings\SettingsContainerInterface;
use Imagick, ImagickDraw, ImagickPixel;
use function is_string;
/**
* ImageMagick output module
* requires ext-imagick
* @link http://php.net/manual/book.imagick.php
* @link http://phpimagick.com
*/
class QRImagick extends QROutputAbstract{
/**
* @var \Imagick
*/
protected $imagick;
/**
* @inheritDoc
* @throws \chillerlan\QRCode\QRCodeException
*/
public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
if(!extension_loaded('imagick')){
throw new QRCodeException('ext-imagick not loaded'); // @codeCoverageIgnore
}
parent::__construct($options, $matrix);
}
/**
* @inheritDoc
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $type => $defaultValue){
$v = $this->options->moduleValues[$type] ?? null;
if(!is_string($v)){
$this->moduleValues[$type] = $defaultValue
? new ImagickPixel($this->options->markupDark)
: new ImagickPixel($this->options->markupLight);
}
else{
$this->moduleValues[$type] = new ImagickPixel($v);
}
}
}
/**
* @inheritDoc
*
* @return string|\Imagick
*/
public function dump(string $file = null){
$file = $file ?? $this->options->cachefile;
$this->imagick = new Imagick;
$this->imagick->newImage(
$this->length,
$this->length,
new ImagickPixel($this->options->imagickBG ?? 'transparent'),
$this->options->imagickFormat
);
$this->drawImage();
if($this->options->returnResource){
return $this->imagick;
}
$imageData = $this->imagick->getImageBlob();
if($file !== null){
$this->saveToFile($imageData, $file);
}
return $imageData;
}
/**
* @return void
*/
protected function drawImage():void{
$draw = new ImagickDraw;
foreach($this->matrix->matrix() as $y => $row){
foreach($row as $x => $M_TYPE){
$draw->setStrokeColor($this->moduleValues[$M_TYPE]);
$draw->setFillColor($this->moduleValues[$M_TYPE]);
$draw->rectangle(
$x * $this->scale,
$y * $this->scale,
($x + 1) * $this->scale,
($y + 1) * $this->scale
);
}
}
$this->imagick->drawImage($draw);
}
}

View File

@@ -0,0 +1,151 @@
<?php
/**
* Class QRMarkup
*
* @filesource QRMarkup.php
* @created 17.12.2016
* @package chillerlan\QRCode\Output
* @author Smiley <smiley@chillerlan.net>
* @copyright 2016 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\QRCode;
use function is_string, sprintf, strip_tags, trim;
/**
* Converts the matrix into markup types: HTML, SVG, ...
*/
class QRMarkup extends QROutputAbstract{
/**
* @var string
*/
protected $defaultMode = QRCode::OUTPUT_MARKUP_SVG;
/**
* @see \sprintf()
*
* @var string
*/
protected $svgHeader = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" class="qr-svg %1$s" style="width: 100%%; height: auto;" viewBox="0 0 %2$d %2$d">';
/**
* @inheritDoc
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_string($v)){
$this->moduleValues[$M_TYPE] = $defaultValue
? $this->options->markupDark
: $this->options->markupLight;
}
else{
$this->moduleValues[$M_TYPE] = trim(strip_tags($v), '\'"');
}
}
}
/**
* @return string
*/
protected function html():string{
$html = '<div class="'.$this->options->cssClass.'">'.$this->options->eol;
foreach($this->matrix->matrix() as $row){
$html .= '<div>';
foreach($row as $M_TYPE){
$html .= '<span style="background: '.$this->moduleValues[$M_TYPE].';"></span>';
}
$html .= '</div>'.$this->options->eol;
}
$html .= '</div>'.$this->options->eol;
if($this->options->cachefile){
return '<!DOCTYPE html><head><meta charset="UTF-8"></head><body>'.$this->options->eol.$html.'</body>';
}
return $html;
}
/**
* @link https://github.com/codemasher/php-qrcode/pull/5
*
* @return string
*/
protected function svg():string{
$matrix = $this->matrix->matrix();
$svg = sprintf($this->svgHeader, $this->options->cssClass, $this->options->svgViewBoxSize ?? $this->moduleCount)
.$this->options->eol
.'<defs>'.$this->options->svgDefs.'</defs>'
.$this->options->eol;
foreach($this->moduleValues as $M_TYPE => $value){
$path = '';
foreach($matrix as $y => $row){
//we'll combine active blocks within a single row as a lightweight compression technique
$start = null;
$count = 0;
foreach($row as $x => $module){
if($module === $M_TYPE){
$count++;
if($start === null){
$start = $x;
}
if(isset($row[$x + 1])){
continue;
}
}
if($count > 0){
$len = $count;
$path .= sprintf('M%s %s h%s v1 h-%sZ ', $start, $y, $len, $len);
// reset count
$count = 0;
$start = null;
}
}
}
if(!empty($path)){
$svg .= sprintf('<path class="qr-%s %s" stroke="transparent" fill="%s" fill-opacity="%s" d="%s" />', $M_TYPE, $this->options->cssClass, $value, $this->options->svgOpacity, $path);
}
}
// close svg
$svg .= '</svg>'.$this->options->eol;
// if saving to file, append the correct headers
if($this->options->cachefile){
return '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'.$this->options->eol.$svg;
}
if($this->options->imageBase64){
$svg = sprintf('data:image/svg+xml;base64,%s', base64_encode($svg));
}
return $svg;
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
* Class QROutputAbstract
*
* @filesource QROutputAbstract.php
* @created 09.12.2015
* @package chillerlan\QRCode\Output
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\{Data\QRMatrix, QRCode};
use chillerlan\Settings\SettingsContainerInterface;
use function call_user_func, dirname, file_put_contents, get_called_class, in_array, is_writable, sprintf;
/**
* common output abstract
*/
abstract class QROutputAbstract implements QROutputInterface{
/**
* @var int
*/
protected $moduleCount;
/**
* @param \chillerlan\QRCode\Data\QRMatrix $matrix
*/
protected $matrix;
/**
* @var \chillerlan\QRCode\QROptions
*/
protected $options;
/**
* @var string
*/
protected $outputMode;
/**
* @var string;
*/
protected $defaultMode;
/**
* @var int
*/
protected $scale;
/**
* @var int
*/
protected $length;
/**
* @var array
*/
protected $moduleValues;
/**
* QROutputAbstract constructor.
*
* @param \chillerlan\Settings\SettingsContainerInterface $options
* @param \chillerlan\QRCode\Data\QRMatrix $matrix
*/
public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
$this->options = $options;
$this->matrix = $matrix;
$this->moduleCount = $this->matrix->size();
$this->scale = $this->options->scale;
$this->length = $this->moduleCount * $this->scale;
$class = get_called_class();
if(isset(QRCode::OUTPUT_MODES[$class]) && in_array($this->options->outputType, QRCode::OUTPUT_MODES[$class])){
$this->outputMode = $this->options->outputType;
}
$this->setModuleValues();
}
/**
* Sets the initial module values (clean-up & defaults)
*
* @return void
*/
abstract protected function setModuleValues():void;
/**
* saves the qr data to a file
*
* @see file_put_contents()
* @see \chillerlan\QRCode\QROptions::cachefile
*
* @param string $data
* @param string $file
*
* @return bool
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
protected function saveToFile(string $data, string $file):bool{
if(!is_writable(dirname($file))){
throw new QRCodeOutputException(sprintf('Could not write data to cache file: %s', $file));
}
return (bool)file_put_contents($file, $data);
}
/**
* @inheritDoc
*/
public function dump(string $file = null){
// call the built-in output method
$data = call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
$file = $file ?? $this->options->cachefile;
if($file !== null){
$this->saveToFile($data, $file);
}
return $data;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Interface QROutputInterface,
*
* @filesource QROutputInterface.php
* @created 02.12.2015
* @package chillerlan\QRCode\Output
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\Data\QRMatrix;
/**
* Converts the data matrix into readable output
*/
interface QROutputInterface{
const DEFAULT_MODULE_VALUES = [
// light
QRMatrix::M_DATA => false, // 4
QRMatrix::M_FINDER => false, // 6
QRMatrix::M_SEPARATOR => false, // 8
QRMatrix::M_ALIGNMENT => false, // 10
QRMatrix::M_TIMING => false, // 12
QRMatrix::M_FORMAT => false, // 14
QRMatrix::M_VERSION => false, // 16
QRMatrix::M_QUIETZONE => false, // 18
QRMatrix::M_LOGO => false, // 20
QRMatrix::M_TEST => false, // 255
// dark
QRMatrix::M_DARKMODULE << 8 => true, // 512
QRMatrix::M_DATA << 8 => true, // 1024
QRMatrix::M_FINDER << 8 => true, // 1536
QRMatrix::M_ALIGNMENT << 8 => true, // 2560
QRMatrix::M_TIMING << 8 => true, // 3072
QRMatrix::M_FORMAT << 8 => true, // 3584
QRMatrix::M_VERSION << 8 => true, // 4096
QRMatrix::M_FINDER_DOT << 8 => true, // 5632
QRMatrix::M_TEST << 8 => true, // 65280
];
/**
* generates the output, optionally dumps it to a file, and returns it
*
* @param string|null $file
*
* @return mixed
*/
public function dump(string $file = null);
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* Class QRString
*
* @filesource QRString.php
* @created 05.12.2015
* @package chillerlan\QRCode\Output
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\QRCode;
use function implode, is_string, json_encode;
/**
* Converts the matrix data into string types
*/
class QRString extends QROutputAbstract{
/**
* @var string
*/
protected $defaultMode = QRCode::OUTPUT_STRING_TEXT;
/**
* @inheritDoc
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_string($v)){
$this->moduleValues[$M_TYPE] = $defaultValue
? $this->options->textDark
: $this->options->textLight;
}
else{
$this->moduleValues[$M_TYPE] = $v;
}
}
}
/**
* @return string
*/
protected function text():string{
$str = [];
foreach($this->matrix->matrix() as $row){
$r = [];
foreach($row as $M_TYPE){
$r[] = $this->moduleValues[$M_TYPE];
}
$str[] = implode('', $r);
}
return implode($this->options->eol, $str);
}
/**
* @return string
*/
protected function json():string{
return json_encode($this->matrix->matrix());
}
}

View File

@@ -0,0 +1,310 @@
<?php
/**
* Class QRCode
*
* @filesource QRCode.php
* @created 26.11.2015
* @package chillerlan\QRCode
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode;
use chillerlan\QRCode\Data\{
MaskPatternTester, QRCodeDataException, QRDataInterface, QRMatrix
};
use chillerlan\QRCode\Output\{
QRCodeOutputException, QRFpdf, QRImage, QRImagick, QRMarkup, QROutputInterface, QRString
};
use chillerlan\Settings\SettingsContainerInterface;
use function array_search, call_user_func_array, class_exists, in_array, min, ord, strlen;
/**
* Turns a text string into a Model 2 QR Code
*
* @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
* @link http://www.qrcode.com/en/codes/model12.html
* @link http://www.thonky.com/qr-code-tutorial/
*/
class QRCode{
/**
* API constants
*/
public const OUTPUT_MARKUP_HTML = 'html';
public const OUTPUT_MARKUP_SVG = 'svg';
public const OUTPUT_IMAGE_PNG = 'png';
public const OUTPUT_IMAGE_JPG = 'jpg';
public const OUTPUT_IMAGE_GIF = 'gif';
public const OUTPUT_STRING_JSON = 'json';
public const OUTPUT_STRING_TEXT = 'text';
public const OUTPUT_IMAGICK = 'imagick';
public const OUTPUT_FPDF = 'fpdf';
public const OUTPUT_CUSTOM = 'custom';
public const VERSION_AUTO = -1;
public const MASK_PATTERN_AUTO = -1;
public const ECC_L = 0b01; // 7%.
public const ECC_M = 0b00; // 15%.
public const ECC_Q = 0b11; // 25%.
public const ECC_H = 0b10; // 30%.
public const DATA_NUMBER = 0b0001;
public const DATA_ALPHANUM = 0b0010;
public const DATA_BYTE = 0b0100;
public const DATA_KANJI = 0b1000;
public const ECC_MODES = [
self::ECC_L => 0,
self::ECC_M => 1,
self::ECC_Q => 2,
self::ECC_H => 3,
];
public const DATA_MODES = [
self::DATA_NUMBER => 0,
self::DATA_ALPHANUM => 1,
self::DATA_BYTE => 2,
self::DATA_KANJI => 3,
];
public const OUTPUT_MODES = [
QRMarkup::class => [
self::OUTPUT_MARKUP_SVG,
self::OUTPUT_MARKUP_HTML,
],
QRImage::class => [
self::OUTPUT_IMAGE_PNG,
self::OUTPUT_IMAGE_GIF,
self::OUTPUT_IMAGE_JPG,
],
QRString::class => [
self::OUTPUT_STRING_JSON,
self::OUTPUT_STRING_TEXT,
],
QRImagick::class => [
self::OUTPUT_IMAGICK,
],
QRFpdf::class => [
self::OUTPUT_FPDF
]
];
/**
* @var \chillerlan\QRCode\QROptions|\chillerlan\Settings\SettingsContainerInterface
*/
protected $options;
/**
* @var \chillerlan\QRCode\Data\QRDataInterface
*/
protected $dataInterface;
/**
* QRCode constructor.
*
* @param \chillerlan\Settings\SettingsContainerInterface|null $options
*/
public function __construct(SettingsContainerInterface $options = null){
$this->options = $options ?? new QROptions;
}
/**
* Renders a QR Code for the given $data and QROptions
*
* @param string $data
* @param string|null $file
*
* @return mixed
*/
public function render(string $data, string $file = null){
return $this->initOutputInterface($data)->dump($file);
}
/**
* Returns a QRMatrix object for the given $data and current QROptions
*
* @param string $data
*
* @return \chillerlan\QRCode\Data\QRMatrix
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function getMatrix(string $data):QRMatrix{
if(empty($data)){
throw new QRCodeDataException('QRCode::getMatrix() No data given.');
}
$this->dataInterface = $this->initDataInterface($data);
$maskPattern = $this->options->maskPattern === $this::MASK_PATTERN_AUTO
? $this->getBestMaskPattern()
: $this->options->maskPattern;
$matrix = $this->dataInterface->initMatrix($maskPattern);
if((bool)$this->options->addQuietzone){
$matrix->setQuietZone($this->options->quietzoneSize);
}
return $matrix;
}
/**
* shoves a QRMatrix through the MaskPatternTester to find the lowest penalty mask pattern
*
* @see \chillerlan\QRCode\Data\MaskPatternTester
*
* @return int
*/
protected function getBestMaskPattern():int{
$penalties = [];
for($pattern = 0; $pattern < 8; $pattern++){
$tester = new MaskPatternTester($this->dataInterface->initMatrix($pattern, true));
$penalties[$pattern] = $tester->testPattern();
}
return array_search(min($penalties), $penalties, true);
}
/**
* returns a fresh QRDataInterface for the given $data
*
* @param string $data
*
* @return \chillerlan\QRCode\Data\QRDataInterface
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function initDataInterface(string $data):QRDataInterface{
$dataModes = ['Number', 'AlphaNum', 'Kanji', 'Byte'];
$dataNamespace = __NAMESPACE__.'\\Data\\';
// allow forcing the data mode
// see https://github.com/chillerlan/php-qrcode/issues/39
if(in_array($this->options->dataMode, $dataModes, true)){
$dataInterface = $dataNamespace.$this->options->dataMode;
return new $dataInterface($this->options, $data);
}
foreach($dataModes as $mode){
$dataInterface = $dataNamespace.$mode;
if(call_user_func_array([$this, 'is'.$mode], [$data]) && class_exists($dataInterface)){
return new $dataInterface($this->options, $data);
}
}
throw new QRCodeDataException('invalid data type'); // @codeCoverageIgnore
}
/**
* returns a fresh (built-in) QROutputInterface
*
* @param string $data
*
* @return \chillerlan\QRCode\Output\QROutputInterface
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
protected function initOutputInterface(string $data):QROutputInterface{
if($this->options->outputType === $this::OUTPUT_CUSTOM && class_exists($this->options->outputInterface)){
return new $this->options->outputInterface($this->options, $this->getMatrix($data));
}
foreach($this::OUTPUT_MODES as $outputInterface => $modes){
if(in_array($this->options->outputType, $modes, true) && class_exists($outputInterface)){
return new $outputInterface($this->options, $this->getMatrix($data));
}
}
throw new QRCodeOutputException('invalid output type');
}
/**
* checks if a string qualifies as numeric
*
* @param string $string
*
* @return bool
*/
public function isNumber(string $string):bool{
return $this->checkString($string, QRDataInterface::NUMBER_CHAR_MAP);
}
/**
* checks if a string qualifies as alphanumeric
*
* @param string $string
*
* @return bool
*/
public function isAlphaNum(string $string):bool{
return $this->checkString($string, QRDataInterface::ALPHANUM_CHAR_MAP);
}
/**
* checks is a given $string matches the characters of a given $charmap, returns false on the first invalid occurence.
*
* @param string $string
* @param array $charmap
*
* @return bool
*/
protected function checkString(string $string, array $charmap):bool{
$len = strlen($string);
for($i = 0; $i < $len; $i++){
if(!in_array($string[$i], $charmap, true)){
return false;
}
}
return true;
}
/**
* checks if a string qualifies as Kanji
*
* @param string $string
*
* @return bool
*/
public function isKanji(string $string):bool{
$i = 0;
$len = strlen($string);
while($i + 1 < $len){
$c = ((0xff & ord($string[$i])) << 8) | (0xff & ord($string[$i + 1]));
if(!($c >= 0x8140 && $c <= 0x9FFC) && !($c >= 0xE040 && $c <= 0xEBBF)){
return false;
}
$i += 2;
}
return $i >= $len;
}
/**
* a dummy
*
* @param $data
*
* @return bool
*/
protected function isByte(string $data):bool{
return !empty($data);
}
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* Class QRCodeException
*
* @filesource QRCodeException.php
* @created 27.11.2015
* @package chillerlan\QRCode
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode;
class QRCodeException extends \Exception{}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Class QROptions
*
* @filesource QROptions.php
* @created 08.12.2015
* @package chillerlan\QRCode
* @author Smiley <smiley@chillerlan.net>
* @copyright 2015 Smiley
* @license MIT
*/
namespace chillerlan\QRCode;
use chillerlan\Settings\SettingsContainerAbstract;
/**
* @property int $version
* @property int $versionMin
* @property int $versionMax
* @property int $eccLevel
* @property int $maskPattern
* @property bool $addQuietzone
* @property bool $quietzoneSize
*
* @property string $dataMode
* @property string $outputType
* @property string $outputInterface
* @property string $cachefile
*
* @property string $eol
* @property int $scale
*
* @property string $cssClass
* @property string $svgOpacity
* @property string $svgDefs
* @property int $svgViewBoxSize
*
* @property string $textDark
* @property string $textLight
*
* @property string $markupDark
* @property string $markupLight
*
* @property bool $returnResource
* @property bool $imageBase64
* @property bool $imageTransparent
* @property array $imageTransparencyBG
* @property int $pngCompression
* @property int $jpegQuality
*
* @property string $imagickFormat
* @property string $imagickBG
*
* @property string $fpdfMeasureUnit
*
* @property array $moduleValues
*/
class QROptions extends SettingsContainerAbstract{
use QROptionsTrait;
}

View File

@@ -0,0 +1,408 @@
<?php
/**
* Trait QROptionsTrait
*
* @filesource QROptionsTrait.php
* @created 10.03.2018
* @package chillerlan\QRCode
* @author smiley <smiley@chillerlan.net>
* @copyright 2018 smiley
* @license MIT
*/
namespace chillerlan\QRCode;
use function array_values, count, in_array, is_array, is_numeric, max, min, sprintf, strtolower;
trait QROptionsTrait{
/**
* QR Code version number
*
* [1 ... 40] or QRCode::VERSION_AUTO
*
* @var int
*/
protected $version = QRCode::VERSION_AUTO;
/**
* Minimum QR version (if $version = QRCode::VERSION_AUTO)
*
* @var int
*/
protected $versionMin = 1;
/**
* Maximum QR version
*
* @var int
*/
protected $versionMax = 40;
/**
* Error correct level
*
* QRCode::ECC_X where X is
* L => 7%
* M => 15%
* Q => 25%
* H => 30%
*
* @var int
*/
protected $eccLevel = QRCode::ECC_L;
/**
* Mask Pattern to use
*
* [0...7] or QRCode::MASK_PATTERN_AUTO
*
* @var int
*/
protected $maskPattern = QRCode::MASK_PATTERN_AUTO;
/**
* Add a "quiet zone" (margin) according to the QR code spec
*
* @var bool
*/
protected $addQuietzone = true;
/**
* Size of the quiet zone
*
* internally clamped to [0 ... $moduleCount / 2], defaults to 4 modules
*
* @var int
*/
protected $quietzoneSize = 4;
/**
* Use this to circumvent the data mode detection and force the usage of the given mode.
* valid modes are: Number, AlphaNum, Kanji, Byte
*
* @see https://github.com/chillerlan/php-qrcode/issues/39
*
* @var string|null
*/
protected $dataMode = null;
/**
* QRCode::OUTPUT_MARKUP_XXXX where XXXX = HTML, SVG
* QRCode::OUTPUT_IMAGE_XXX where XXX = PNG, GIF, JPG
* QRCode::OUTPUT_STRING_XXXX where XXXX = TEXT, JSON
* QRCode::OUTPUT_CUSTOM
*
* @var string
*/
protected $outputType = QRCode::OUTPUT_IMAGE_PNG;
/**
* the FQCN of the custom QROutputInterface if $outputType is set to QRCode::OUTPUT_CUSTOM
*
* @var string|null
*/
protected $outputInterface = null;
/**
* /path/to/cache.file
*
* @var string|null
*/
protected $cachefile = null;
/**
* newline string [HTML, SVG, TEXT]
*
* @var string
*/
protected $eol = PHP_EOL;
/**
* size of a QR code pixel [SVG, IMAGE_*]
* HTML -> via CSS
*
* @var int
*/
protected $scale = 5;
/**
* a common css class
*
* @var string
*/
protected $cssClass = '';
/**
* SVG opacity
*
* @var float
*/
protected $svgOpacity = 1.0;
/**
* anything between <defs>
*
* @see https://developer.mozilla.org/docs/Web/SVG/Element/defs
*
* @var string
*/
protected $svgDefs = '<style>rect{shape-rendering:crispEdges}</style>';
/**
* SVG viewBox size. a single integer number which defines width/height of the viewBox attribute.
*
* viewBox="0 0 x x"
*
* @see https://css-tricks.com/scale-svg/#article-header-id-3
*
* @var int|null
*/
protected $svgViewBoxSize = null;
/**
* string substitute for dark
*
* @var string
*/
protected $textDark = '🔴';
/**
* string substitute for light
*
* @var string
*/
protected $textLight = '⭕';
/**
* markup substitute for dark (CSS value)
*
* @var string
*/
protected $markupDark = '#000';
/**
* markup substitute for light (CSS value)
*
* @var string
*/
protected $markupLight = '#fff';
/**
* Return the image resource instead of a render if applicable.
* This option overrides other output options, such as $cachefile and $imageBase64.
*
* Supported by the following modules:
*
* - QRImage: resource
* - QRImagick: Imagick
* - QRFpdf: FPDF
*
* @see \chillerlan\QRCode\Output\QROutputInterface::dump()
*
* @var bool
*/
protected $returnResource = false;
/**
* toggle base64 or raw image data
*
* @var bool
*/
protected $imageBase64 = true;
/**
* toggle transparency, not supported by jpg
*
* @var bool
*/
protected $imageTransparent = true;
/**
* @see imagecolortransparent()
*
* @var array [R, G, B]
*/
protected $imageTransparencyBG = [255, 255, 255];
/**
* @see imagepng()
*
* @var int
*/
protected $pngCompression = -1;
/**
* @see imagejpeg()
*
* @var int
*/
protected $jpegQuality = 85;
/**
* Imagick output format
*
* @see Imagick::setType()
*
* @var string
*/
protected $imagickFormat = 'png';
/**
* Imagick background color (defaults to "transparent")
*
* @see \ImagickPixel::__construct()
*
* @var string|null
*/
protected $imagickBG = null;
/**
* Measurement unit for FPDF output: pt, mm, cm, in (defaults to "pt")
*
* @see \FPDF::__construct()
*/
protected $fpdfMeasureUnit = 'pt';
/**
* Module values map
*
* HTML, IMAGICK: #ABCDEF, cssname, rgb(), rgba()...
* IMAGE: [63, 127, 255] // R, G, B
*
* @var array|null
*/
protected $moduleValues = null;
/**
* clamp min/max version number
*
* @param int $versionMin
* @param int $versionMax
*
* @return void
*/
protected function setMinMaxVersion(int $versionMin, int $versionMax):void{
$min = max(1, min(40, $versionMin));
$max = max(1, min(40, $versionMax));
$this->versionMin = min($min, $max);
$this->versionMax = max($min, $max);
}
/**
* sets the minimum version number
*
* @param int $version
*
* @return void
*/
protected function set_versionMin(int $version):void{
$this->setMinMaxVersion($version, $this->versionMax);
}
/**
* sets the maximum version number
*
* @param int $version
*
* @return void
*/
protected function set_versionMax(int $version):void{
$this->setMinMaxVersion($this->versionMin, $version);
}
/**
* sets the error correction level
*
* @param int $eccLevel
*
* @return void
* @throws \chillerlan\QRCode\QRCodeException
*/
protected function set_eccLevel(int $eccLevel):void{
if(!isset(QRCode::ECC_MODES[$eccLevel])){
throw new QRCodeException(sprintf('Invalid error correct level: %s', $eccLevel));
}
$this->eccLevel = $eccLevel;
}
/**
* sets/clamps the mask pattern
*
* @param int $maskPattern
*
* @return void
*/
protected function set_maskPattern(int $maskPattern):void{
if($maskPattern !== QRCode::MASK_PATTERN_AUTO){
$this->maskPattern = max(0, min(7, $maskPattern));
}
}
/**
* sets the transparency background color
*
* @param mixed $imageTransparencyBG
*
* @return void
* @throws \chillerlan\QRCode\QRCodeException
*/
protected function set_imageTransparencyBG($imageTransparencyBG):void{
// invalid value - set to white as default
if(!is_array($imageTransparencyBG) || count($imageTransparencyBG) < 3){
$this->imageTransparencyBG = [255, 255, 255];
return;
}
foreach($imageTransparencyBG as $k => $v){
if(!is_numeric($v)){
throw new QRCodeException('Invalid RGB value.');
}
// clamp the values
$this->imageTransparencyBG[$k] = max(0, min(255, (int)$v));
}
// use the array values to not run into errors with the spread operator (...$arr)
$this->imageTransparencyBG = array_values($this->imageTransparencyBG);
}
/**
* sets/clamps the version number
*
* @param int $version
*
* @return void
*/
protected function set_version(int $version):void{
if($version !== QRCode::VERSION_AUTO){
$this->version = max(1, min(40, $version));
}
}
/**
* sets the FPDF measurement unit
*
* @codeCoverageIgnore
*/
protected function set_fpdfMeasureUnit(string $unit):void{
$unit = strtolower($unit);
if(in_array($unit, ['cm', 'in', 'mm', 'pt'], true)){
$this->fpdfMeasureUnit = $unit;
}
// @todo throw or ignore silently?
}
}

View File

@@ -0,0 +1,5 @@
filter:
excluded_paths:
- examples/*
- tests/*
- vendor/*

View File

@@ -0,0 +1,18 @@
language: php
matrix:
include:
- php: 7.2
- php: 7.3
- php: 7.4
- php: 8.0
- php: nightly
allow_failures:
- php: nightly
before_script: travis_retry composer install --no-interaction --prefer-source
script: vendor/bin/phpunit --configuration phpunit.xml --coverage-clover clover.xml
after_script: bash <(curl -s https://codecov.io/bash)

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Smiley <smiley@chillerlan.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,46 @@
<?php
/**
* @filesource advanced.php
* @created 28.08.2018
* @author smiley <smiley@chillerlan.net>
* @copyright 2018 smiley
* @license MIT
*/
namespace chillerlan\SettingsExamples;
use chillerlan\Settings\SettingsContainerAbstract;
require_once __DIR__.'/../vendor/autoload.php';
// from library #1
trait SomeOptions{
protected $foo;
// this method will be called in SettingsContainerAbstract::__construct() after the properties have been set
protected function SomeOptions(){
// just some constructor stuff...
$this->foo = strtoupper($this->foo);
}
}
// from library #2
trait MoreOptions{
protected $bar = 'whatever'; // provide default values
}
$commonOptions = [
// SomeOptions
'foo' => 'whatever',
// MoreOptions
'bar' => 'nothing',
];
// now plug the several library options together to a single object
/** @var \chillerlan\Settings\SettingsContainerInterface $container */
$container = new class ($commonOptions) extends SettingsContainerAbstract{
use SomeOptions, MoreOptions; // ...
};
var_dump($container->foo); // -> WHATEVER (constructor ran strtoupper on the value)
var_dump($container->bar); // -> nothing

View File

@@ -0,0 +1,30 @@
<?php
/**
* @filesource simple.php
* @created 28.08.2018
* @author smiley <smiley@chillerlan.net>
* @copyright 2018 smiley
* @license MIT
*/
namespace chillerlan\SettingsExamples;
use chillerlan\Settings\SettingsContainerAbstract;
require_once __DIR__.'/../vendor/autoload.php';
class MyContainer extends SettingsContainerAbstract{
protected $foo;
protected $bar;
}
/** @var \chillerlan\Settings\SettingsContainerInterface $container */
$container = new MyContainer(['foo' => 'what']);
$container->bar = 'foo';
var_dump($container->toJSON()); // -> {"foo":"what","bar":"foo"}
// non-existing properties will be ignored:
$container->nope = 'what';
var_dump($container->nope); // -> NULL

View File

@@ -0,0 +1,35 @@
<?xml version="1.0"?>
<ruleset name="codemasher/php-settings-container PMD ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>codemasher/php-settings-container PMD ruleset</description>
<exclude-pattern>*/examples/*</exclude-pattern>
<exclude-pattern>*/tests/*</exclude-pattern>
<exclude-pattern>*/vendor/*</exclude-pattern>
<rule ref="rulesets/cleancode.xml">
<exclude name="BooleanArgumentFlag"/>
</rule>
<rule ref="rulesets/codesize.xml/CyclomaticComplexity">
<priority>1</priority>
<properties>
<property name="maximum" value="150" />
</properties>
</rule>
<rule ref="rulesets/controversial.xml">
<exclude name="CamelCaseMethodName"/>
<exclude name="CamelCasePropertyName"/>
<exclude name="CamelCaseParameterName"/>
<exclude name="CamelCaseVariableName"/>
</rule>
<rule ref="rulesets/design.xml">
</rule>
<rule ref="rulesets/naming.xml">
<exclude name="LongVariable"/>
<exclude name="ShortVariable"/>
</rule>
<rule ref="rulesets/unusedcode.xml">
<exclude name="UnusedFormalParameter"/>
</rule>
</ruleset>

View File

@@ -0,0 +1,172 @@
<?php
/**
* Class SettingsContainerAbstract
*
* @filesource SettingsContainerAbstract.php
* @created 28.08.2018
* @package chillerlan\Settings
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/
namespace chillerlan\Settings;
use Exception, ReflectionClass, ReflectionProperty;
use function call_user_func, call_user_func_array, get_object_vars, json_decode, json_encode, method_exists, property_exists;
abstract class SettingsContainerAbstract implements SettingsContainerInterface{
/**
* SettingsContainerAbstract constructor.
*
* @param iterable|null $properties
*/
public function __construct(iterable $properties = null){
if(!empty($properties)){
$this->fromIterable($properties);
}
$this->construct();
}
/**
* calls a method with trait name as replacement constructor for each used trait
* (remember pre-php5 classname constructors? yeah, basically this.)
*
* @return void
*/
protected function construct():void{
$traits = (new ReflectionClass($this))->getTraits();
foreach($traits as $trait){
$method = $trait->getShortName();
if(method_exists($this, $method)){
call_user_func([$this, $method]);
}
}
}
/**
* @inheritdoc
*/
public function __get(string $property){
if(property_exists($this, $property) && !$this->isPrivate($property)){
if(method_exists($this, 'get_'.$property)){
return call_user_func([$this, 'get_'.$property]);
}
return $this->{$property};
}
return null;
}
/**
* @inheritdoc
*/
public function __set(string $property, $value):void{
if(!property_exists($this, $property) || $this->isPrivate($property)){
return;
}
if(method_exists($this, 'set_'.$property)){
call_user_func_array([$this, 'set_'.$property], [$value]);
return;
}
$this->{$property} = $value;
}
/**
* @inheritdoc
*/
public function __isset(string $property):bool{
return isset($this->{$property}) && !$this->isPrivate($property);
}
/**
* @internal Checks if a property is private
*
* @param string $property
*
* @return bool
*/
protected function isPrivate(string $property):bool{
return (new ReflectionProperty($this, $property))->isPrivate();
}
/**
* @inheritdoc
*/
public function __unset(string $property):void{
if($this->__isset($property)){
unset($this->{$property});
}
}
/**
* @inheritdoc
*/
public function __toString():string{
return $this->toJSON();
}
/**
* @inheritdoc
*/
public function toArray():array{
return get_object_vars($this);
}
/**
* @inheritdoc
*/
public function fromIterable(iterable $properties):SettingsContainerInterface{
foreach($properties as $key => $value){
$this->__set($key, $value);
}
return $this;
}
/**
* @inheritdoc
*/
public function toJSON(int $jsonOptions = null):string{
return json_encode($this, $jsonOptions ?? 0);
}
/**
* @inheritdoc
*/
public function fromJSON(string $json):SettingsContainerInterface{
$data = json_decode($json, true); // as of PHP 7.3: JSON_THROW_ON_ERROR
if($data === false || $data === null){
throw new Exception('error while decoding JSON');
}
return $this->fromIterable($data);
}
/**
* @inheritdoc
*/
public function jsonSerialize(){
return $this->toArray();
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Interface SettingsContainerInterface
*
* @filesource SettingsContainerInterface.php
* @created 28.08.2018
* @package chillerlan\Settings
* @author Smiley <smiley@chillerlan.net>
* @copyright 2018 Smiley
* @license MIT
*/
namespace chillerlan\Settings;
use JsonSerializable;
/**
* a generic container with magic getter and setter
*/
interface SettingsContainerInterface extends JsonSerializable{
/**
* Retrieve the value of $property
*
* @param string $property
*
* @return mixed
*/
public function __get(string $property);
/**
* Set $property to $value while avoiding private and non-existing properties
*
* @param string $property
* @param mixed $value
*
* @return void
*/
public function __set(string $property, $value):void;
/**
* Checks if $property is set (aka. not null), excluding private properties
*
* @param string $property
*
* @return bool
*/
public function __isset(string $property):bool;
/**
* Unsets $property while avoiding private and non-existing properties
*
* @param string $property
*
* @return void
*/
public function __unset(string $property):void;
/**
* @see SettingsContainerInterface::toJSON()
*
* @return string
*/
public function __toString():string;
/**
* Returns an array representation of the settings object
*
* @return array
*/
public function toArray():array;
/**
* Sets properties from a given iterable
*
* @param iterable $properties
*
* @return \chillerlan\Settings\SettingsContainerInterface
*/
public function fromIterable(iterable $properties):SettingsContainerInterface;
/**
* Returns a JSON representation of the settings object
* @see \json_encode()
*
* @param int|null $jsonOptions
*
* @return string
*/
public function toJSON(int $jsonOptions = null):string;
/**
* Sets properties from a given JSON string
*
* @param string $json
*
* @return \chillerlan\Settings\SettingsContainerInterface
*
* @throws \Exception
* @throws \JsonException
*/
public function fromJSON(string $json):SettingsContainerInterface;
}

View File

@@ -0,0 +1,585 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see https://www.php-fig.org/psr/psr-0/
* @see https://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return string[]
*/
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
}
return array();
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
return $this->classMap;
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
* @return void
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*
* @return void
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*
* @return void
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
*
* @param string|null $apcuPrefix
*
* @return void
*/
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
}
/**
* The APCu prefix in use, or null if APCu caching is not enabled.
*
* @return string|null
*/
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
if (null === $this->vendorDir) {
return;
}
if ($prepend) {
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
} else {
unset(self::$registeredLoaders[$this->vendorDir]);
self::$registeredLoaders[$this->vendorDir] = $this;
}
}
/**
* Unregisters this instance as an autoloader.
*
* @return void
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
if (null !== $this->vendorDir) {
unset(self::$registeredLoaders[$this->vendorDir]);
}
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return true|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
return null;
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
return false;
}
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
return $file;
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return self[]
*/
public static function getRegisteredLoaders()
{
return self::$registeredLoaders;
}
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($this->prefixDirsPsr4[$search])) {
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($this->prefixDirsPsr4[$search] as $dir) {
if (file_exists($file = $dir . $pathEnd)) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
return false;
}
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View File

@@ -0,0 +1,359 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer;
use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;
/**
* This class is copied in every Composer installed project and available to all
*
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
*
* To require its presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/
class InstalledVersions
{
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array();
/**
* Returns a list of all package names which are present, either by being installed, replaced or provided
*
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackages()
{
$packages = array();
foreach (self::getInstalled() as $installed) {
$packages[] = array_keys($installed['versions']);
}
if (1 === \count($packages)) {
return $packages[0];
}
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
}
/**
* Returns a list of all package names with a specific type e.g. 'library'
*
* @param string $type
* @return string[]
* @psalm-return list<string>
*/
public static function getInstalledPackagesByType($type)
{
$packagesByType = array();
foreach (self::getInstalled() as $installed) {
foreach ($installed['versions'] as $name => $package) {
if (isset($package['type']) && $package['type'] === $type) {
$packagesByType[] = $name;
}
}
}
return $packagesByType;
}
/**
* Checks whether the given package is installed
*
* This also returns true if the package name is provided or replaced by another package
*
* @param string $packageName
* @param bool $includeDevRequirements
* @return bool
*/
public static function isInstalled($packageName, $includeDevRequirements = true)
{
foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
}
}
return false;
}
/**
* Checks whether the given package satisfies a version constraint
*
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
*
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
*
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
* @param string $packageName
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
* @return bool
*/
public static function satisfies(VersionParser $parser, $packageName, $constraint)
{
$constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint);
}
/**
* Returns a version constraint representing all the range(s) which are installed for a given package
*
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
* whether a given version of a package is installed, and not just whether it exists
*
* @param string $packageName
* @return string Version constraint usable with composer/semver
*/
public static function getVersionRanges($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
$ranges = array();
if (isset($installed['versions'][$packageName]['pretty_version'])) {
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
}
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
}
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
}
if (array_key_exists('provided', $installed['versions'][$packageName])) {
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
}
return implode(' || ', $ranges);
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['version'])) {
return null;
}
return $installed['versions'][$packageName]['version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
*/
public static function getPrettyVersion($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
return null;
}
return $installed['versions'][$packageName]['pretty_version'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
*/
public static function getReference($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
if (!isset($installed['versions'][$packageName]['reference'])) {
return null;
}
return $installed['versions'][$packageName]['reference'];
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @param string $packageName
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
*/
public static function getInstallPath($packageName)
{
foreach (self::getInstalled() as $installed) {
if (!isset($installed['versions'][$packageName])) {
continue;
}
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
}
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
}
/**
* @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/
public static function getRootPackage()
{
$installed = self::getInstalled();
return $installed[0]['root'];
}
/**
* Returns the raw installed.php data for custom implementations
*
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
*/
public static function getRawData()
{
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
self::$installed = include __DIR__ . '/installed.php';
} else {
self::$installed = array();
}
}
return self::$installed;
}
/**
* Returns the raw data of all installed.php which are currently loaded for custom implementations
*
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
public static function getAllRawData()
{
return self::getInstalled();
}
/**
* Lets you reload the static array from another file
*
* This is only useful for complex integrations in which a project needs to use
* this class but then also needs to execute another project's autoloader in process,
* and wants to ensure both projects have access to their version of installed.php.
*
* A typical case would be PHPUnit, where it would need to make sure it reads all
* the data it needs from this class, then call reload() with
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
* the project in which it runs can then also use this class safely, without
* interference between PHPUnit's dependencies and the project's dependencies.
*
* @param array[] $data A vendor/composer/installed.php data set
* @return void
*
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
*/
public static function reload($data)
{
self::$installed = $data;
self::$installedByVendor = array();
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static function getInstalled()
{
if (null === self::$canGetVendors) {
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
}
$installed = array();
if (self::$canGetVendors) {
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require $vendorDir.'/composer/installed.php';
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1];
}
}
}
}
if (null === self::$installed) {
// only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else {
self::$installed = array();
}
}
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
return $installed;
}
}

View File

@@ -0,0 +1,21 @@
Copyright (c) Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,181 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
'PayEye\\App' => $baseDir . '/src/App.php',
'PayEye\\Entity\\CartMapping' => $baseDir . '/src/Entity/CartMapping.php',
'PayEye\\Entity\\ReturnEntity' => $baseDir . '/src/Entity/ReturnEntity.php',
'PayEye\\Entity\\ReturnProductEntity' => $baseDir . '/src/Entity/ReturnProductEntity.php',
'PayEye\\GatewayLoader' => $baseDir . '/src/GatewayLoader.php',
'PayEye\\Gateway\\PayEyeGateway' => $baseDir . '/src/Gateway/PayEyeGateway.php',
'PayEye\\Hooks' => $baseDir . '/src/Hooks.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceDisablePayEyeCouponForAnotherPayments' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceDisablePayEyeCouponForAnotherPayments.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceDisablePayEyeGatewayInStandardProcess' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceDisablePayEyeGatewayInStandardProcess.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceDisplayOrderMetaData' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceDisplayOrderMetaData.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceFreeShippingCoupon' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceFreeShippingCoupon.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceMappingSessionKeyToCartId' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceMappingSessionKeyToCartId.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceMetaBoxCoupon' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceMetaBoxCoupon.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceOrderStatuses' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceOrderStatuses.php',
'PayEye\\Hooks\\WooCommerce\\WoocommercePayEyeReturnsMetaBox' => $baseDir . '/src/Hooks/WooCommerce/WoocommercePayEyeReturnsMetaBox.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceRefreshCart' => $baseDir . '/src/Hooks/WooCommerce/WoocommerceRefreshCart.php',
'PayEye\\Hooks\\Wordpress\\WordpressAjaxReturn' => $baseDir . '/src/Hooks/Wordpress/WordpressAjaxReturn.php',
'PayEye\\Hooks\\Wordpress\\WordpressAjaxReturnStatus' => $baseDir . '/src/Hooks/Wordpress/WordpressAjaxReturnStatus.php',
'PayEye\\Hooks\\Wordpress\\WordpressAjaxWidget' => $baseDir . '/src/Hooks/Wordpress/WordpressAjaxWidget.php',
'PayEye\\Hooks\\Wordpress\\WordpressEnqueueScripts' => $baseDir . '/src/Hooks/Wordpress/WordpressEnqueueScripts.php',
'PayEye\\Hooks\\Wordpress\\WordpressPluginActionLinks' => $baseDir . '/src/Hooks/Wordpress/WordpressPluginActionLinks.php',
'PayEye\\Lib\\Auth\\AuthConfig' => $vendorDir . '/payeye/lib/src/Auth/AuthConfig.php',
'PayEye\\Lib\\Auth\\AuthRequest' => $vendorDir . '/payeye/lib/src/Auth/AuthRequest.php',
'PayEye\\Lib\\Auth\\AuthService' => $vendorDir . '/payeye/lib/src/Auth/AuthService.php',
'PayEye\\Lib\\Auth\\HashService' => $vendorDir . '/payeye/lib/src/Auth/HashService.php',
'PayEye\\Lib\\Cart\\CartRequestModel' => $vendorDir . '/payeye/lib/src/Cart/CartRequestModel.php',
'PayEye\\Lib\\Cart\\CartResponseModel' => $vendorDir . '/payeye/lib/src/Cart/CartResponseModel.php',
'PayEye\\Lib\\Deeplink\\Deeplink' => $vendorDir . '/payeye/lib/src/Deeplink/Deeplink.php',
'PayEye\\Lib\\Enum\\ErrorCode' => $vendorDir . '/payeye/lib/src/Enum/ErrorCode.php',
'PayEye\\Lib\\Enum\\HttpStatus' => $vendorDir . '/payeye/lib/src/Enum/HttpStatus.php',
'PayEye\\Lib\\Enum\\OrderStatus' => $vendorDir . '/payeye/lib/src/Enum/OrderStatus.php',
'PayEye\\Lib\\Enum\\PickupPointType' => $vendorDir . '/payeye/lib/src/Enum/PickupPointType.php',
'PayEye\\Lib\\Enum\\PromoCodeType' => $vendorDir . '/payeye/lib/src/Enum/PromoCodeType.php',
'PayEye\\Lib\\Enum\\ReturnStatus' => $vendorDir . '/payeye/lib/src/Enum/ReturnStatus.php',
'PayEye\\Lib\\Enum\\ShippingProvider' => $vendorDir . '/payeye/lib/src/Enum/ShippingProvider.php',
'PayEye\\Lib\\Enum\\SignatureFrom' => $vendorDir . '/payeye/lib/src/Enum/SignatureFrom.php',
'PayEye\\Lib\\Enum\\TransferStatus' => $vendorDir . '/payeye/lib/src/Enum/TransferStatus.php',
'PayEye\\Lib\\Env\\Config' => $vendorDir . '/payeye/lib/src/Env/Config.php',
'PayEye\\Lib\\Exception\\CartContentNotMatchedException' => $vendorDir . '/payeye/lib/src/Exception/CartContentNotMatchedException.php',
'PayEye\\Lib\\Exception\\CartEmptyException' => $vendorDir . '/payeye/lib/src/Exception/CartEmptyException.php',
'PayEye\\Lib\\Exception\\CartNotFoundException' => $vendorDir . '/payeye/lib/src/Exception/CartNotFoundException.php',
'PayEye\\Lib\\Exception\\CouponAppliedException' => $vendorDir . '/payeye/lib/src/Exception/CouponAppliedException.php',
'PayEye\\Lib\\Exception\\InvalidCartStockException' => $vendorDir . '/payeye/lib/src/Exception/InvalidCartStockException.php',
'PayEye\\Lib\\Exception\\InvalidCouponException' => $vendorDir . '/payeye/lib/src/Exception/InvalidCouponException.php',
'PayEye\\Lib\\Exception\\InvalidPostCodeException' => $vendorDir . '/payeye/lib/src/Exception/InvalidPostCodeException.php',
'PayEye\\Lib\\Exception\\InvalidShippingException' => $vendorDir . '/payeye/lib/src/Exception/InvalidShippingException.php',
'PayEye\\Lib\\Exception\\OrderAlreadyExistsException' => $vendorDir . '/payeye/lib/src/Exception/OrderAlreadyExistsException.php',
'PayEye\\Lib\\Exception\\OrderFailedException' => $vendorDir . '/payeye/lib/src/Exception/OrderFailedException.php',
'PayEye\\Lib\\Exception\\OrderNotFoundException' => $vendorDir . '/payeye/lib/src/Exception/OrderNotFoundException.php',
'PayEye\\Lib\\Exception\\OrderPaidException' => $vendorDir . '/payeye/lib/src/Exception/OrderPaidException.php',
'PayEye\\Lib\\Exception\\OrderPriceNotMatchedException' => $vendorDir . '/payeye/lib/src/Exception/OrderPriceNotMatchedException.php',
'PayEye\\Lib\\Exception\\PayEyePaymentException' => $vendorDir . '/payeye/lib/src/Exception/PayEyePaymentException.php',
'PayEye\\Lib\\Exception\\PaymentMethodIsDisabledException' => $vendorDir . '/payeye/lib/src/Exception/PaymentMethodIsDisabledException.php',
'PayEye\\Lib\\Exception\\ReturnNotFoundException' => $vendorDir . '/payeye/lib/src/Exception/ReturnNotFoundException.php',
'PayEye\\Lib\\Exception\\ShippingProviderNotMatchedException' => $vendorDir . '/payeye/lib/src/Exception/ShippingProviderNotMatchedException.php',
'PayEye\\Lib\\Exception\\ShopIdDoesNotMatchException' => $vendorDir . '/payeye/lib/src/Exception/ShopIdDoesNotMatchException.php',
'PayEye\\Lib\\Exception\\SignatureNotMatchedException' => $vendorDir . '/payeye/lib/src/Exception/SignatureNotMatchedException.php',
'PayEye\\Lib\\Exception\\WoocommerceException' => $vendorDir . '/payeye/lib/src/Exception/WoocommerceException.php',
'PayEye\\Lib\\HttpClient\\Enum\\EvenType' => $vendorDir . '/payeye/lib/src/HttpClient/Enum/EvenType.php',
'PayEye\\Lib\\HttpClient\\Exception\\HttpException' => $vendorDir . '/payeye/lib/src/HttpClient/Exception/HttpException.php',
'PayEye\\Lib\\HttpClient\\Exception\\HttpNetworkException' => $vendorDir . '/payeye/lib/src/HttpClient/Exception/HttpNetworkException.php',
'PayEye\\Lib\\HttpClient\\Infrastructure\\HttpClient' => $vendorDir . '/payeye/lib/src/HttpClient/Infrastructure/HttpClient.php',
'PayEye\\Lib\\HttpClient\\Model\\ErrorResponse' => $vendorDir . '/payeye/lib/src/HttpClient/Model/ErrorResponse.php',
'PayEye\\Lib\\HttpClient\\Model\\HttpResponse' => $vendorDir . '/payeye/lib/src/HttpClient/Model/HttpResponse.php',
'PayEye\\Lib\\HttpClient\\Model\\RefreshCartRequest' => $vendorDir . '/payeye/lib/src/HttpClient/Model/RefreshCartRequest.php',
'PayEye\\Lib\\HttpClient\\Model\\RefreshCartResponse' => $vendorDir . '/payeye/lib/src/HttpClient/Model/RefreshCartResponse.php',
'PayEye\\Lib\\HttpClient\\Model\\ReturnStatusRequest' => $vendorDir . '/payeye/lib/src/HttpClient/Model/ReturnStatusRequest.php',
'PayEye\\Lib\\HttpClient\\Model\\ReturnStatusResponse' => $vendorDir . '/payeye/lib/src/HttpClient/Model/ReturnStatusResponse.php',
'PayEye\\Lib\\HttpClient\\PayEyeHttpClient' => $vendorDir . '/payeye/lib/src/HttpClient/PayEyeHttpClient.php',
'PayEye\\Lib\\Model\\Address' => $vendorDir . '/payeye/lib/src/Model/Address.php',
'PayEye\\Lib\\Model\\Billing' => $vendorDir . '/payeye/lib/src/Model/Billing.php',
'PayEye\\Lib\\Model\\Cart' => $vendorDir . '/payeye/lib/src/Model/Cart.php',
'PayEye\\Lib\\Model\\Invoice' => $vendorDir . '/payeye/lib/src/Model/Invoice.php',
'PayEye\\Lib\\Model\\Location' => $vendorDir . '/payeye/lib/src/Model/Location.php',
'PayEye\\Lib\\Model\\PickupPoint' => $vendorDir . '/payeye/lib/src/Model/PickupPoint.php',
'PayEye\\Lib\\Model\\Product' => $vendorDir . '/payeye/lib/src/Model/Product.php',
'PayEye\\Lib\\Model\\ProductAttribute' => $vendorDir . '/payeye/lib/src/Model/ProductAttribute.php',
'PayEye\\Lib\\Model\\ProductImages' => $vendorDir . '/payeye/lib/src/Model/ProductImages.php',
'PayEye\\Lib\\Model\\PromoCode' => $vendorDir . '/payeye/lib/src/Model/PromoCode.php',
'PayEye\\Lib\\Model\\RefundProduct' => $vendorDir . '/payeye/lib/src/Model/RefundProduct.php',
'PayEye\\Lib\\Model\\Shipping' => $vendorDir . '/payeye/lib/src/Model/Shipping.php',
'PayEye\\Lib\\Model\\ShippingMethod' => $vendorDir . '/payeye/lib/src/Model/ShippingMethod.php',
'PayEye\\Lib\\Model\\Shop' => $vendorDir . '/payeye/lib/src/Model/Shop.php',
'PayEye\\Lib\\Order\\OrderCreateRequestModel' => $vendorDir . '/payeye/lib/src/Order/OrderCreateRequestModel.php',
'PayEye\\Lib\\Order\\OrderCreateResponseModel' => $vendorDir . '/payeye/lib/src/Order/OrderCreateResponseModel.php',
'PayEye\\Lib\\Order\\OrderUpdateStatusRequestModel' => $vendorDir . '/payeye/lib/src/Order/OrderUpdateStatusRequestModel.php',
'PayEye\\Lib\\Order\\OrderUpdateStatusResponseModel' => $vendorDir . '/payeye/lib/src/Order/OrderUpdateStatusResponseModel.php',
'PayEye\\Lib\\PromoCode\\PromoCodeRequestModel' => $vendorDir . '/payeye/lib/src/PromoCode/PromoCodeRequestModel.php',
'PayEye\\Lib\\PromoCode\\PromoCodeResponseModel' => $vendorDir . '/payeye/lib/src/PromoCode/PromoCodeResponseModel.php',
'PayEye\\Lib\\Returns\\ReturnCreateRequestModel' => $vendorDir . '/payeye/lib/src/Returns/ReturnCreateRequestModel.php',
'PayEye\\Lib\\Returns\\ReturnCreateResponseModel' => $vendorDir . '/payeye/lib/src/Returns/ReturnCreateResponseModel.php',
'PayEye\\Lib\\Returns\\ReturnUpdateStatusRequestModel' => $vendorDir . '/payeye/lib/src/Returns/ReturnUpdateStatusRequestModel.php',
'PayEye\\Lib\\Returns\\ReturnUpdateStatusResponseModel' => $vendorDir . '/payeye/lib/src/Returns/ReturnUpdateStatusResponseModel.php',
'PayEye\\Lib\\Service\\AmountService' => $vendorDir . '/payeye/lib/src/Service/AmountService.php',
'PayEye\\Lib\\Test\\TestCaseTrait' => $vendorDir . '/payeye/lib/src/Test/TestCaseTrait.php',
'PayEye\\Lib\\Tool\\Builder' => $vendorDir . '/payeye/lib/src/Tool/Builder.php',
'PayEye\\Lib\\Tool\\JsonHelper' => $vendorDir . '/payeye/lib/src/Tool/JsonHelper.php',
'PayEye\\Lib\\Tool\\Uuid' => $vendorDir . '/payeye/lib/src/Tool/Uuid.php',
'PayEye\\Lib\\Widget\\Model\\WidgetCartModel' => $vendorDir . '/payeye/lib/src/Widget/Model/WidgetCartModel.php',
'PayEye\\Lib\\Widget\\WidgetModel' => $vendorDir . '/payeye/lib/src/Widget/WidgetModel.php',
'PayEye\\Lib\\Widget\\WidgetStatusModel' => $vendorDir . '/payeye/lib/src/Widget/WidgetStatusModel.php',
'PayEye\\REST\\Cart\\Controllers\\GetCartController' => $baseDir . '/src/REST/Cart/Controllers/GetCartController.php',
'PayEye\\REST\\Cart\\Controllers\\RestartStatusCartController' => $baseDir . '/src/REST/Cart/Controllers/RestartStatusCartController.php',
'PayEye\\REST\\Cart\\Controllers\\StatusCartController' => $baseDir . '/src/REST/Cart/Controllers/StatusCartController.php',
'PayEye\\REST\\Cart\\Model\\StatusCartRequestModel' => $baseDir . '/src/REST/Cart/Model/StatusCartRequestModel.php',
'PayEye\\REST\\Cart\\Model\\StatusCartResponseModel' => $baseDir . '/src/REST/Cart/Model/StatusCartResponseModel.php',
'PayEye\\REST\\Coupon\\Controllers\\ApplyCouponController' => $baseDir . '/src/REST/Coupon/Controllers/ApplyCouponController.php',
'PayEye\\REST\\Coupon\\Controllers\\RemoveCouponController' => $baseDir . '/src/REST/Coupon/Controllers/RemoveCouponController.php',
'PayEye\\REST\\Merchant\\Controllers\\VerifyKeysController' => $baseDir . '/src/REST/Merchant/Controllers/VerifyKeysController.php',
'PayEye\\REST\\Merchant\\Model\\VerifyKeyRequestModel' => $baseDir . '/src/REST/Merchant/Model/VerifyKeyRequestModel.php',
'PayEye\\REST\\Order\\Controllers\\CreateOrderController' => $baseDir . '/src/REST/Order/Controllers/CreateOrderController.php',
'PayEye\\REST\\Order\\Controllers\\UpdateStatusOrderController' => $baseDir . '/src/REST/Order/Controllers/UpdateStatusOrderController.php',
'PayEye\\REST\\Order\\Enum\\WooCommerceOrderStatus' => $baseDir . '/src/REST/Order/Enum/WooCommerceOrderStatus.php',
'PayEye\\REST\\REST' => $baseDir . '/src/REST/REST.php',
'PayEye\\REST\\Returns\\Controllers\\CreateReturnController' => $baseDir . '/src/REST/Returns/Controllers/CreateReturnController.php',
'PayEye\\REST\\Returns\\Controllers\\UpdateReturnStatusController' => $baseDir . '/src/REST/Returns/Controllers/UpdateReturnStatusController.php',
'PayEye\\Repository\\CartMappingRepository' => $baseDir . '/src/Repository/CartMappingRepository.php',
'PayEye\\Repository\\CouponRepository' => $baseDir . '/src/Repository/CouponRepository.php',
'PayEye\\Repository\\Returns\\ReturnProductRepository' => $baseDir . '/src/Repository/Returns/ReturnProductRepository.php',
'PayEye\\Repository\\Returns\\ReturnRepository' => $baseDir . '/src/Repository/Returns/ReturnRepository.php',
'PayEye\\Repository\\WoocommerceSessionRepository' => $baseDir . '/src/Repository/WoocommerceSessionRepository.php',
'PayEye\\Repository\\WordpressOptionsRepository' => $baseDir . '/src/Repository/WordpressOptionsRepository.php',
'PayEye\\Services\\Cart\\CartService' => $baseDir . '/src/Services/Cart/CartService.php',
'PayEye\\Services\\Coupon\\CouponHelper' => $baseDir . '/src/Services/Coupon/CouponHelper.php',
'PayEye\\Services\\Coupon\\CouponService' => $baseDir . '/src/Services/Coupon/CouponService.php',
'PayEye\\Services\\Shipping\\Enum\\ShippingType' => $baseDir . '/src/Services/Shipping/Enum/ShippingType.php',
'PayEye\\Services\\Shipping\\ShippingService' => $baseDir . '/src/Services/Shipping/ShippingService.php',
'PayEye\\Shared\\Collection' => $baseDir . '/src/Shared/Collection.php',
'PayEye\\Shared\\Controllers\\BaseController' => $baseDir . '/src/Shared/Controllers/BaseController.php',
'PayEye\\Shared\\Enums\\AjaxActionType' => $baseDir . '/src/Shared/Enums/AjaxActionType.php',
'PayEye\\Shared\\Enums\\GuardType' => $baseDir . '/src/Shared/Enums/GuardType.php',
'PayEye\\Shared\\Enums\\OrderMetaKey' => $baseDir . '/src/Shared/Enums/OrderMetaKey.php',
'PayEye\\Shared\\Enums\\ShippingRateMetaKey' => $baseDir . '/src/Shared/Enums/ShippingRateMetaKey.php',
'PayEye\\Shared\\Helpers\\PluginActiveHelper' => $baseDir . '/src/Shared/Helpers/PluginActiveHelper.php',
'PayEye\\Shared\\Logger' => $baseDir . '/src/Shared/Logger.php',
'PayEye\\Shared\\Model\\ShippingMatch' => $baseDir . '/src/Shared/Model/ShippingMatch.php',
'PayEye\\Shared\\Model\\ShippingMatchCollection' => $baseDir . '/src/Shared/Model/ShippingMatchCollection.php',
'PayEye\\Shared\\PluginData' => $baseDir . '/src/Shared/PluginData.php',
'PayEye\\Shared\\RegisterHookInterface' => $baseDir . '/src/Shared/RegisterHookInterface.php',
'PayEye\\Shared\\RestRequestInterface' => $baseDir . '/src/Shared/RestRequestInterface.php',
'PayEye\\Shared\\Schema\\RestSchema' => $baseDir . '/src/Shared/Schema/RestSchema.php',
'PayEye\\Shared\\Schema\\RestSchemaType' => $baseDir . '/src/Shared/Schema/RestSchemaType.php',
'PayEye\\Shared\\TemporaryConfig' => $baseDir . '/src/Shared/TemporaryConfig.php',
'PayEye\\Shared\\Woocommerce\\Checkout' => $baseDir . '/src/Shared/Woocommerce/Checkout.php',
'PayEye\\Shared\\Woocommerce\\SessionHandler' => $baseDir . '/src/Shared/Woocommerce/SessionHandler.php',
'PayEye\\Util\\DataTimeUtil' => $baseDir . '/src/Util/DataTimeUtil.php',
'chillerlan\\QRCode\\Data\\AlphaNum' => $vendorDir . '/chillerlan/php-qrcode/src/Data/AlphaNum.php',
'chillerlan\\QRCode\\Data\\Byte' => $vendorDir . '/chillerlan/php-qrcode/src/Data/Byte.php',
'chillerlan\\QRCode\\Data\\Kanji' => $vendorDir . '/chillerlan/php-qrcode/src/Data/Kanji.php',
'chillerlan\\QRCode\\Data\\MaskPatternTester' => $vendorDir . '/chillerlan/php-qrcode/src/Data/MaskPatternTester.php',
'chillerlan\\QRCode\\Data\\Number' => $vendorDir . '/chillerlan/php-qrcode/src/Data/Number.php',
'chillerlan\\QRCode\\Data\\QRCodeDataException' => $vendorDir . '/chillerlan/php-qrcode/src/Data/QRCodeDataException.php',
'chillerlan\\QRCode\\Data\\QRDataAbstract' => $vendorDir . '/chillerlan/php-qrcode/src/Data/QRDataAbstract.php',
'chillerlan\\QRCode\\Data\\QRDataInterface' => $vendorDir . '/chillerlan/php-qrcode/src/Data/QRDataInterface.php',
'chillerlan\\QRCode\\Data\\QRMatrix' => $vendorDir . '/chillerlan/php-qrcode/src/Data/QRMatrix.php',
'chillerlan\\QRCode\\Helpers\\BitBuffer' => $vendorDir . '/chillerlan/php-qrcode/src/Helpers/BitBuffer.php',
'chillerlan\\QRCode\\Helpers\\Polynomial' => $vendorDir . '/chillerlan/php-qrcode/src/Helpers/Polynomial.php',
'chillerlan\\QRCode\\Output\\QRCodeOutputException' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QRCodeOutputException.php',
'chillerlan\\QRCode\\Output\\QRFpdf' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QRFpdf.php',
'chillerlan\\QRCode\\Output\\QRImage' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QRImage.php',
'chillerlan\\QRCode\\Output\\QRImagick' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QRImagick.php',
'chillerlan\\QRCode\\Output\\QRMarkup' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QRMarkup.php',
'chillerlan\\QRCode\\Output\\QROutputAbstract' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QROutputAbstract.php',
'chillerlan\\QRCode\\Output\\QROutputInterface' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QROutputInterface.php',
'chillerlan\\QRCode\\Output\\QRString' => $vendorDir . '/chillerlan/php-qrcode/src/Output/QRString.php',
'chillerlan\\QRCode\\QRCode' => $vendorDir . '/chillerlan/php-qrcode/src/QRCode.php',
'chillerlan\\QRCode\\QRCodeException' => $vendorDir . '/chillerlan/php-qrcode/src/QRCodeException.php',
'chillerlan\\QRCode\\QROptions' => $vendorDir . '/chillerlan/php-qrcode/src/QROptions.php',
'chillerlan\\QRCode\\QROptionsTrait' => $vendorDir . '/chillerlan/php-qrcode/src/QROptionsTrait.php',
'chillerlan\\Settings\\SettingsContainerAbstract' => $vendorDir . '/chillerlan/php-settings-container/src/SettingsContainerAbstract.php',
'chillerlan\\Settings\\SettingsContainerInterface' => $vendorDir . '/chillerlan/php-settings-container/src/SettingsContainerInterface.php',
);

View File

@@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
);

View File

@@ -0,0 +1,13 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'chillerlan\\Settings\\' => array($vendorDir . '/chillerlan/php-settings-container/src'),
'chillerlan\\QRCode\\' => array($vendorDir . '/chillerlan/php-qrcode/src'),
'PayEye\\Lib\\' => array($vendorDir . '/payeye/lib/src'),
'PayEye\\' => array($baseDir . '/src'),
);

View File

@@ -0,0 +1,38 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit55743d547c1e55e064902e9a43db0e45
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
/**
* @return \Composer\Autoload\ClassLoader
*/
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit55743d547c1e55e064902e9a43db0e45', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit55743d547c1e55e064902e9a43db0e45', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit55743d547c1e55e064902e9a43db0e45::getInitializer($loader));
$loader->register(true);
return $loader;
}
}

View File

@@ -0,0 +1,225 @@
<?php
// autoload_static.php @generated by Composer
namespace Composer\Autoload;
class ComposerStaticInit55743d547c1e55e064902e9a43db0e45
{
public static $prefixLengthsPsr4 = array (
'c' =>
array (
'chillerlan\\Settings\\' => 20,
'chillerlan\\QRCode\\' => 18,
),
'P' =>
array (
'PayEye\\Lib\\' => 11,
'PayEye\\' => 7,
),
);
public static $prefixDirsPsr4 = array (
'chillerlan\\Settings\\' =>
array (
0 => __DIR__ . '/..' . '/chillerlan/php-settings-container/src',
),
'chillerlan\\QRCode\\' =>
array (
0 => __DIR__ . '/..' . '/chillerlan/php-qrcode/src',
),
'PayEye\\Lib\\' =>
array (
0 => __DIR__ . '/..' . '/payeye/lib/src',
),
'PayEye\\' =>
array (
0 => __DIR__ . '/../..' . '/src',
),
);
public static $classMap = array (
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
'PayEye\\App' => __DIR__ . '/../..' . '/src/App.php',
'PayEye\\Entity\\CartMapping' => __DIR__ . '/../..' . '/src/Entity/CartMapping.php',
'PayEye\\Entity\\ReturnEntity' => __DIR__ . '/../..' . '/src/Entity/ReturnEntity.php',
'PayEye\\Entity\\ReturnProductEntity' => __DIR__ . '/../..' . '/src/Entity/ReturnProductEntity.php',
'PayEye\\GatewayLoader' => __DIR__ . '/../..' . '/src/GatewayLoader.php',
'PayEye\\Gateway\\PayEyeGateway' => __DIR__ . '/../..' . '/src/Gateway/PayEyeGateway.php',
'PayEye\\Hooks' => __DIR__ . '/../..' . '/src/Hooks.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceDisablePayEyeCouponForAnotherPayments' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceDisablePayEyeCouponForAnotherPayments.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceDisablePayEyeGatewayInStandardProcess' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceDisablePayEyeGatewayInStandardProcess.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceDisplayOrderMetaData' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceDisplayOrderMetaData.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceFreeShippingCoupon' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceFreeShippingCoupon.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceMappingSessionKeyToCartId' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceMappingSessionKeyToCartId.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceMetaBoxCoupon' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceMetaBoxCoupon.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceOrderStatuses' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceOrderStatuses.php',
'PayEye\\Hooks\\WooCommerce\\WoocommercePayEyeReturnsMetaBox' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommercePayEyeReturnsMetaBox.php',
'PayEye\\Hooks\\WooCommerce\\WoocommerceRefreshCart' => __DIR__ . '/../..' . '/src/Hooks/WooCommerce/WoocommerceRefreshCart.php',
'PayEye\\Hooks\\Wordpress\\WordpressAjaxReturn' => __DIR__ . '/../..' . '/src/Hooks/Wordpress/WordpressAjaxReturn.php',
'PayEye\\Hooks\\Wordpress\\WordpressAjaxReturnStatus' => __DIR__ . '/../..' . '/src/Hooks/Wordpress/WordpressAjaxReturnStatus.php',
'PayEye\\Hooks\\Wordpress\\WordpressAjaxWidget' => __DIR__ . '/../..' . '/src/Hooks/Wordpress/WordpressAjaxWidget.php',
'PayEye\\Hooks\\Wordpress\\WordpressEnqueueScripts' => __DIR__ . '/../..' . '/src/Hooks/Wordpress/WordpressEnqueueScripts.php',
'PayEye\\Hooks\\Wordpress\\WordpressPluginActionLinks' => __DIR__ . '/../..' . '/src/Hooks/Wordpress/WordpressPluginActionLinks.php',
'PayEye\\Lib\\Auth\\AuthConfig' => __DIR__ . '/..' . '/payeye/lib/src/Auth/AuthConfig.php',
'PayEye\\Lib\\Auth\\AuthRequest' => __DIR__ . '/..' . '/payeye/lib/src/Auth/AuthRequest.php',
'PayEye\\Lib\\Auth\\AuthService' => __DIR__ . '/..' . '/payeye/lib/src/Auth/AuthService.php',
'PayEye\\Lib\\Auth\\HashService' => __DIR__ . '/..' . '/payeye/lib/src/Auth/HashService.php',
'PayEye\\Lib\\Cart\\CartRequestModel' => __DIR__ . '/..' . '/payeye/lib/src/Cart/CartRequestModel.php',
'PayEye\\Lib\\Cart\\CartResponseModel' => __DIR__ . '/..' . '/payeye/lib/src/Cart/CartResponseModel.php',
'PayEye\\Lib\\Deeplink\\Deeplink' => __DIR__ . '/..' . '/payeye/lib/src/Deeplink/Deeplink.php',
'PayEye\\Lib\\Enum\\ErrorCode' => __DIR__ . '/..' . '/payeye/lib/src/Enum/ErrorCode.php',
'PayEye\\Lib\\Enum\\HttpStatus' => __DIR__ . '/..' . '/payeye/lib/src/Enum/HttpStatus.php',
'PayEye\\Lib\\Enum\\OrderStatus' => __DIR__ . '/..' . '/payeye/lib/src/Enum/OrderStatus.php',
'PayEye\\Lib\\Enum\\PickupPointType' => __DIR__ . '/..' . '/payeye/lib/src/Enum/PickupPointType.php',
'PayEye\\Lib\\Enum\\PromoCodeType' => __DIR__ . '/..' . '/payeye/lib/src/Enum/PromoCodeType.php',
'PayEye\\Lib\\Enum\\ReturnStatus' => __DIR__ . '/..' . '/payeye/lib/src/Enum/ReturnStatus.php',
'PayEye\\Lib\\Enum\\ShippingProvider' => __DIR__ . '/..' . '/payeye/lib/src/Enum/ShippingProvider.php',
'PayEye\\Lib\\Enum\\SignatureFrom' => __DIR__ . '/..' . '/payeye/lib/src/Enum/SignatureFrom.php',
'PayEye\\Lib\\Enum\\TransferStatus' => __DIR__ . '/..' . '/payeye/lib/src/Enum/TransferStatus.php',
'PayEye\\Lib\\Env\\Config' => __DIR__ . '/..' . '/payeye/lib/src/Env/Config.php',
'PayEye\\Lib\\Exception\\CartContentNotMatchedException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/CartContentNotMatchedException.php',
'PayEye\\Lib\\Exception\\CartEmptyException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/CartEmptyException.php',
'PayEye\\Lib\\Exception\\CartNotFoundException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/CartNotFoundException.php',
'PayEye\\Lib\\Exception\\CouponAppliedException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/CouponAppliedException.php',
'PayEye\\Lib\\Exception\\InvalidCartStockException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/InvalidCartStockException.php',
'PayEye\\Lib\\Exception\\InvalidCouponException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/InvalidCouponException.php',
'PayEye\\Lib\\Exception\\InvalidPostCodeException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/InvalidPostCodeException.php',
'PayEye\\Lib\\Exception\\InvalidShippingException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/InvalidShippingException.php',
'PayEye\\Lib\\Exception\\OrderAlreadyExistsException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/OrderAlreadyExistsException.php',
'PayEye\\Lib\\Exception\\OrderFailedException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/OrderFailedException.php',
'PayEye\\Lib\\Exception\\OrderNotFoundException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/OrderNotFoundException.php',
'PayEye\\Lib\\Exception\\OrderPaidException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/OrderPaidException.php',
'PayEye\\Lib\\Exception\\OrderPriceNotMatchedException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/OrderPriceNotMatchedException.php',
'PayEye\\Lib\\Exception\\PayEyePaymentException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/PayEyePaymentException.php',
'PayEye\\Lib\\Exception\\PaymentMethodIsDisabledException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/PaymentMethodIsDisabledException.php',
'PayEye\\Lib\\Exception\\ReturnNotFoundException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/ReturnNotFoundException.php',
'PayEye\\Lib\\Exception\\ShippingProviderNotMatchedException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/ShippingProviderNotMatchedException.php',
'PayEye\\Lib\\Exception\\ShopIdDoesNotMatchException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/ShopIdDoesNotMatchException.php',
'PayEye\\Lib\\Exception\\SignatureNotMatchedException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/SignatureNotMatchedException.php',
'PayEye\\Lib\\Exception\\WoocommerceException' => __DIR__ . '/..' . '/payeye/lib/src/Exception/WoocommerceException.php',
'PayEye\\Lib\\HttpClient\\Enum\\EvenType' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Enum/EvenType.php',
'PayEye\\Lib\\HttpClient\\Exception\\HttpException' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Exception/HttpException.php',
'PayEye\\Lib\\HttpClient\\Exception\\HttpNetworkException' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Exception/HttpNetworkException.php',
'PayEye\\Lib\\HttpClient\\Infrastructure\\HttpClient' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Infrastructure/HttpClient.php',
'PayEye\\Lib\\HttpClient\\Model\\ErrorResponse' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Model/ErrorResponse.php',
'PayEye\\Lib\\HttpClient\\Model\\HttpResponse' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Model/HttpResponse.php',
'PayEye\\Lib\\HttpClient\\Model\\RefreshCartRequest' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Model/RefreshCartRequest.php',
'PayEye\\Lib\\HttpClient\\Model\\RefreshCartResponse' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Model/RefreshCartResponse.php',
'PayEye\\Lib\\HttpClient\\Model\\ReturnStatusRequest' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Model/ReturnStatusRequest.php',
'PayEye\\Lib\\HttpClient\\Model\\ReturnStatusResponse' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/Model/ReturnStatusResponse.php',
'PayEye\\Lib\\HttpClient\\PayEyeHttpClient' => __DIR__ . '/..' . '/payeye/lib/src/HttpClient/PayEyeHttpClient.php',
'PayEye\\Lib\\Model\\Address' => __DIR__ . '/..' . '/payeye/lib/src/Model/Address.php',
'PayEye\\Lib\\Model\\Billing' => __DIR__ . '/..' . '/payeye/lib/src/Model/Billing.php',
'PayEye\\Lib\\Model\\Cart' => __DIR__ . '/..' . '/payeye/lib/src/Model/Cart.php',
'PayEye\\Lib\\Model\\Invoice' => __DIR__ . '/..' . '/payeye/lib/src/Model/Invoice.php',
'PayEye\\Lib\\Model\\Location' => __DIR__ . '/..' . '/payeye/lib/src/Model/Location.php',
'PayEye\\Lib\\Model\\PickupPoint' => __DIR__ . '/..' . '/payeye/lib/src/Model/PickupPoint.php',
'PayEye\\Lib\\Model\\Product' => __DIR__ . '/..' . '/payeye/lib/src/Model/Product.php',
'PayEye\\Lib\\Model\\ProductAttribute' => __DIR__ . '/..' . '/payeye/lib/src/Model/ProductAttribute.php',
'PayEye\\Lib\\Model\\ProductImages' => __DIR__ . '/..' . '/payeye/lib/src/Model/ProductImages.php',
'PayEye\\Lib\\Model\\PromoCode' => __DIR__ . '/..' . '/payeye/lib/src/Model/PromoCode.php',
'PayEye\\Lib\\Model\\RefundProduct' => __DIR__ . '/..' . '/payeye/lib/src/Model/RefundProduct.php',
'PayEye\\Lib\\Model\\Shipping' => __DIR__ . '/..' . '/payeye/lib/src/Model/Shipping.php',
'PayEye\\Lib\\Model\\ShippingMethod' => __DIR__ . '/..' . '/payeye/lib/src/Model/ShippingMethod.php',
'PayEye\\Lib\\Model\\Shop' => __DIR__ . '/..' . '/payeye/lib/src/Model/Shop.php',
'PayEye\\Lib\\Order\\OrderCreateRequestModel' => __DIR__ . '/..' . '/payeye/lib/src/Order/OrderCreateRequestModel.php',
'PayEye\\Lib\\Order\\OrderCreateResponseModel' => __DIR__ . '/..' . '/payeye/lib/src/Order/OrderCreateResponseModel.php',
'PayEye\\Lib\\Order\\OrderUpdateStatusRequestModel' => __DIR__ . '/..' . '/payeye/lib/src/Order/OrderUpdateStatusRequestModel.php',
'PayEye\\Lib\\Order\\OrderUpdateStatusResponseModel' => __DIR__ . '/..' . '/payeye/lib/src/Order/OrderUpdateStatusResponseModel.php',
'PayEye\\Lib\\PromoCode\\PromoCodeRequestModel' => __DIR__ . '/..' . '/payeye/lib/src/PromoCode/PromoCodeRequestModel.php',
'PayEye\\Lib\\PromoCode\\PromoCodeResponseModel' => __DIR__ . '/..' . '/payeye/lib/src/PromoCode/PromoCodeResponseModel.php',
'PayEye\\Lib\\Returns\\ReturnCreateRequestModel' => __DIR__ . '/..' . '/payeye/lib/src/Returns/ReturnCreateRequestModel.php',
'PayEye\\Lib\\Returns\\ReturnCreateResponseModel' => __DIR__ . '/..' . '/payeye/lib/src/Returns/ReturnCreateResponseModel.php',
'PayEye\\Lib\\Returns\\ReturnUpdateStatusRequestModel' => __DIR__ . '/..' . '/payeye/lib/src/Returns/ReturnUpdateStatusRequestModel.php',
'PayEye\\Lib\\Returns\\ReturnUpdateStatusResponseModel' => __DIR__ . '/..' . '/payeye/lib/src/Returns/ReturnUpdateStatusResponseModel.php',
'PayEye\\Lib\\Service\\AmountService' => __DIR__ . '/..' . '/payeye/lib/src/Service/AmountService.php',
'PayEye\\Lib\\Test\\TestCaseTrait' => __DIR__ . '/..' . '/payeye/lib/src/Test/TestCaseTrait.php',
'PayEye\\Lib\\Tool\\Builder' => __DIR__ . '/..' . '/payeye/lib/src/Tool/Builder.php',
'PayEye\\Lib\\Tool\\JsonHelper' => __DIR__ . '/..' . '/payeye/lib/src/Tool/JsonHelper.php',
'PayEye\\Lib\\Tool\\Uuid' => __DIR__ . '/..' . '/payeye/lib/src/Tool/Uuid.php',
'PayEye\\Lib\\Widget\\Model\\WidgetCartModel' => __DIR__ . '/..' . '/payeye/lib/src/Widget/Model/WidgetCartModel.php',
'PayEye\\Lib\\Widget\\WidgetModel' => __DIR__ . '/..' . '/payeye/lib/src/Widget/WidgetModel.php',
'PayEye\\Lib\\Widget\\WidgetStatusModel' => __DIR__ . '/..' . '/payeye/lib/src/Widget/WidgetStatusModel.php',
'PayEye\\REST\\Cart\\Controllers\\GetCartController' => __DIR__ . '/../..' . '/src/REST/Cart/Controllers/GetCartController.php',
'PayEye\\REST\\Cart\\Controllers\\RestartStatusCartController' => __DIR__ . '/../..' . '/src/REST/Cart/Controllers/RestartStatusCartController.php',
'PayEye\\REST\\Cart\\Controllers\\StatusCartController' => __DIR__ . '/../..' . '/src/REST/Cart/Controllers/StatusCartController.php',
'PayEye\\REST\\Cart\\Model\\StatusCartRequestModel' => __DIR__ . '/../..' . '/src/REST/Cart/Model/StatusCartRequestModel.php',
'PayEye\\REST\\Cart\\Model\\StatusCartResponseModel' => __DIR__ . '/../..' . '/src/REST/Cart/Model/StatusCartResponseModel.php',
'PayEye\\REST\\Coupon\\Controllers\\ApplyCouponController' => __DIR__ . '/../..' . '/src/REST/Coupon/Controllers/ApplyCouponController.php',
'PayEye\\REST\\Coupon\\Controllers\\RemoveCouponController' => __DIR__ . '/../..' . '/src/REST/Coupon/Controllers/RemoveCouponController.php',
'PayEye\\REST\\Merchant\\Controllers\\VerifyKeysController' => __DIR__ . '/../..' . '/src/REST/Merchant/Controllers/VerifyKeysController.php',
'PayEye\\REST\\Merchant\\Model\\VerifyKeyRequestModel' => __DIR__ . '/../..' . '/src/REST/Merchant/Model/VerifyKeyRequestModel.php',
'PayEye\\REST\\Order\\Controllers\\CreateOrderController' => __DIR__ . '/../..' . '/src/REST/Order/Controllers/CreateOrderController.php',
'PayEye\\REST\\Order\\Controllers\\UpdateStatusOrderController' => __DIR__ . '/../..' . '/src/REST/Order/Controllers/UpdateStatusOrderController.php',
'PayEye\\REST\\Order\\Enum\\WooCommerceOrderStatus' => __DIR__ . '/../..' . '/src/REST/Order/Enum/WooCommerceOrderStatus.php',
'PayEye\\REST\\REST' => __DIR__ . '/../..' . '/src/REST/REST.php',
'PayEye\\REST\\Returns\\Controllers\\CreateReturnController' => __DIR__ . '/../..' . '/src/REST/Returns/Controllers/CreateReturnController.php',
'PayEye\\REST\\Returns\\Controllers\\UpdateReturnStatusController' => __DIR__ . '/../..' . '/src/REST/Returns/Controllers/UpdateReturnStatusController.php',
'PayEye\\Repository\\CartMappingRepository' => __DIR__ . '/../..' . '/src/Repository/CartMappingRepository.php',
'PayEye\\Repository\\CouponRepository' => __DIR__ . '/../..' . '/src/Repository/CouponRepository.php',
'PayEye\\Repository\\Returns\\ReturnProductRepository' => __DIR__ . '/../..' . '/src/Repository/Returns/ReturnProductRepository.php',
'PayEye\\Repository\\Returns\\ReturnRepository' => __DIR__ . '/../..' . '/src/Repository/Returns/ReturnRepository.php',
'PayEye\\Repository\\WoocommerceSessionRepository' => __DIR__ . '/../..' . '/src/Repository/WoocommerceSessionRepository.php',
'PayEye\\Repository\\WordpressOptionsRepository' => __DIR__ . '/../..' . '/src/Repository/WordpressOptionsRepository.php',
'PayEye\\Services\\Cart\\CartService' => __DIR__ . '/../..' . '/src/Services/Cart/CartService.php',
'PayEye\\Services\\Coupon\\CouponHelper' => __DIR__ . '/../..' . '/src/Services/Coupon/CouponHelper.php',
'PayEye\\Services\\Coupon\\CouponService' => __DIR__ . '/../..' . '/src/Services/Coupon/CouponService.php',
'PayEye\\Services\\Shipping\\Enum\\ShippingType' => __DIR__ . '/../..' . '/src/Services/Shipping/Enum/ShippingType.php',
'PayEye\\Services\\Shipping\\ShippingService' => __DIR__ . '/../..' . '/src/Services/Shipping/ShippingService.php',
'PayEye\\Shared\\Collection' => __DIR__ . '/../..' . '/src/Shared/Collection.php',
'PayEye\\Shared\\Controllers\\BaseController' => __DIR__ . '/../..' . '/src/Shared/Controllers/BaseController.php',
'PayEye\\Shared\\Enums\\AjaxActionType' => __DIR__ . '/../..' . '/src/Shared/Enums/AjaxActionType.php',
'PayEye\\Shared\\Enums\\GuardType' => __DIR__ . '/../..' . '/src/Shared/Enums/GuardType.php',
'PayEye\\Shared\\Enums\\OrderMetaKey' => __DIR__ . '/../..' . '/src/Shared/Enums/OrderMetaKey.php',
'PayEye\\Shared\\Enums\\ShippingRateMetaKey' => __DIR__ . '/../..' . '/src/Shared/Enums/ShippingRateMetaKey.php',
'PayEye\\Shared\\Helpers\\PluginActiveHelper' => __DIR__ . '/../..' . '/src/Shared/Helpers/PluginActiveHelper.php',
'PayEye\\Shared\\Logger' => __DIR__ . '/../..' . '/src/Shared/Logger.php',
'PayEye\\Shared\\Model\\ShippingMatch' => __DIR__ . '/../..' . '/src/Shared/Model/ShippingMatch.php',
'PayEye\\Shared\\Model\\ShippingMatchCollection' => __DIR__ . '/../..' . '/src/Shared/Model/ShippingMatchCollection.php',
'PayEye\\Shared\\PluginData' => __DIR__ . '/../..' . '/src/Shared/PluginData.php',
'PayEye\\Shared\\RegisterHookInterface' => __DIR__ . '/../..' . '/src/Shared/RegisterHookInterface.php',
'PayEye\\Shared\\RestRequestInterface' => __DIR__ . '/../..' . '/src/Shared/RestRequestInterface.php',
'PayEye\\Shared\\Schema\\RestSchema' => __DIR__ . '/../..' . '/src/Shared/Schema/RestSchema.php',
'PayEye\\Shared\\Schema\\RestSchemaType' => __DIR__ . '/../..' . '/src/Shared/Schema/RestSchemaType.php',
'PayEye\\Shared\\TemporaryConfig' => __DIR__ . '/../..' . '/src/Shared/TemporaryConfig.php',
'PayEye\\Shared\\Woocommerce\\Checkout' => __DIR__ . '/../..' . '/src/Shared/Woocommerce/Checkout.php',
'PayEye\\Shared\\Woocommerce\\SessionHandler' => __DIR__ . '/../..' . '/src/Shared/Woocommerce/SessionHandler.php',
'PayEye\\Util\\DataTimeUtil' => __DIR__ . '/../..' . '/src/Util/DataTimeUtil.php',
'chillerlan\\QRCode\\Data\\AlphaNum' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/AlphaNum.php',
'chillerlan\\QRCode\\Data\\Byte' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/Byte.php',
'chillerlan\\QRCode\\Data\\Kanji' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/Kanji.php',
'chillerlan\\QRCode\\Data\\MaskPatternTester' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/MaskPatternTester.php',
'chillerlan\\QRCode\\Data\\Number' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/Number.php',
'chillerlan\\QRCode\\Data\\QRCodeDataException' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/QRCodeDataException.php',
'chillerlan\\QRCode\\Data\\QRDataAbstract' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/QRDataAbstract.php',
'chillerlan\\QRCode\\Data\\QRDataInterface' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/QRDataInterface.php',
'chillerlan\\QRCode\\Data\\QRMatrix' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Data/QRMatrix.php',
'chillerlan\\QRCode\\Helpers\\BitBuffer' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Helpers/BitBuffer.php',
'chillerlan\\QRCode\\Helpers\\Polynomial' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Helpers/Polynomial.php',
'chillerlan\\QRCode\\Output\\QRCodeOutputException' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QRCodeOutputException.php',
'chillerlan\\QRCode\\Output\\QRFpdf' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QRFpdf.php',
'chillerlan\\QRCode\\Output\\QRImage' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QRImage.php',
'chillerlan\\QRCode\\Output\\QRImagick' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QRImagick.php',
'chillerlan\\QRCode\\Output\\QRMarkup' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QRMarkup.php',
'chillerlan\\QRCode\\Output\\QROutputAbstract' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QROutputAbstract.php',
'chillerlan\\QRCode\\Output\\QROutputInterface' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QROutputInterface.php',
'chillerlan\\QRCode\\Output\\QRString' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/Output/QRString.php',
'chillerlan\\QRCode\\QRCode' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/QRCode.php',
'chillerlan\\QRCode\\QRCodeException' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/QRCodeException.php',
'chillerlan\\QRCode\\QROptions' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/QROptions.php',
'chillerlan\\QRCode\\QROptionsTrait' => __DIR__ . '/..' . '/chillerlan/php-qrcode/src/QROptionsTrait.php',
'chillerlan\\Settings\\SettingsContainerAbstract' => __DIR__ . '/..' . '/chillerlan/php-settings-container/src/SettingsContainerAbstract.php',
'chillerlan\\Settings\\SettingsContainerInterface' => __DIR__ . '/..' . '/chillerlan/php-settings-container/src/SettingsContainerInterface.php',
);
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit55743d547c1e55e064902e9a43db0e45::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit55743d547c1e55e064902e9a43db0e45::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit55743d547c1e55e064902e9a43db0e45::$classMap;
}, null, ClassLoader::class);
}
}

View File

@@ -0,0 +1,179 @@
{
"packages": [
{
"name": "chillerlan/php-qrcode",
"version": "3.4.1",
"version_normalized": "3.4.1.0",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-qrcode.git",
"reference": "468603b687a5fe75c1ff33857a45f1726c7b95a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/468603b687a5fe75c1ff33857a45f1726c7b95a9",
"reference": "468603b687a5fe75c1ff33857a45f1726c7b95a9",
"shasum": ""
},
"require": {
"chillerlan/php-settings-container": "^1.2.2",
"ext-mbstring": "*",
"php": "^7.2 || ^8.0"
},
"require-dev": {
"phan/phan": "^3.2.2",
"phpunit/phpunit": "^8.5",
"setasign/fpdf": "^1.8.2"
},
"suggest": {
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
"setasign/fpdf": "Required to use the QR FPDF output."
},
"time": "2021-09-03T17:54:45+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"chillerlan\\QRCode\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kazuhiko Arase",
"homepage": "https://github.com/kazuhikoarase"
},
{
"name": "Smiley",
"email": "smiley@chillerlan.net",
"homepage": "https://github.com/codemasher"
},
{
"name": "Contributors",
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
}
],
"description": "A QR code generator. PHP 7.2+",
"homepage": "https://github.com/chillerlan/php-qrcode",
"keywords": [
"phpqrcode",
"qr",
"qr code",
"qrcode",
"qrcode-generator"
],
"support": {
"issues": "https://github.com/chillerlan/php-qrcode/issues",
"source": "https://github.com/chillerlan/php-qrcode/tree/3.4.1"
},
"funding": [
{
"url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4",
"type": "custom"
},
{
"url": "https://ko-fi.com/codemasher",
"type": "ko_fi"
}
],
"install-path": "../chillerlan/php-qrcode"
},
{
"name": "chillerlan/php-settings-container",
"version": "1.2.2",
"version_normalized": "1.2.2.0",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-settings-container.git",
"reference": "d1b5284d6eb3a767459738bb0b20073f0cb3eeaf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/d1b5284d6eb3a767459738bb0b20073f0cb3eeaf",
"reference": "d1b5284d6eb3a767459738bb0b20073f0cb3eeaf",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.2 || ^8.0"
},
"require-dev": {
"phpunit/phpunit": "^8.4"
},
"time": "2021-09-03T17:33:25+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"chillerlan\\Settings\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Smiley",
"email": "smiley@chillerlan.net",
"homepage": "https://github.com/codemasher"
}
],
"description": "A container class for immutable settings objects. Not a DI container. PHP 7.2+",
"homepage": "https://github.com/chillerlan/php-settings-container",
"keywords": [
"PHP7",
"Settings",
"container",
"helper"
],
"support": {
"issues": "https://github.com/chillerlan/php-settings-container/issues",
"source": "https://github.com/chillerlan/php-settings-container"
},
"funding": [
{
"url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4",
"type": "custom"
},
{
"url": "https://ko-fi.com/codemasher",
"type": "ko_fi"
}
],
"install-path": "../chillerlan/php-settings-container"
},
{
"name": "payeye/lib",
"version": "1.18.13",
"version_normalized": "1.18.13.0",
"source": {
"type": "git",
"url": "https://gitlab.com/payeye2/frontend216/ecommerce/ecommerce-php-library.git",
"reference": "c00935223fd34c32116b6e5bd2907808cce8961d"
},
"dist": {
"type": "zip",
"url": "https://gitlab.com/api/v4/projects/42726542/packages/composer/archives/payeye/lib.zip?sha=c00935223fd34c32116b6e5bd2907808cce8961d",
"reference": "c00935223fd34c32116b6e5bd2907808cce8961d",
"shasum": ""
},
"require": {
"ext-curl": "*"
},
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"PayEye\\Lib\\": "src/"
}
},
"install-path": "../payeye/lib"
}
],
"dev": false,
"dev-package-names": []
}

View File

@@ -0,0 +1,50 @@
<?php return array(
'root' => array(
'name' => 'payeye/woocommerce',
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'reference' => NULL,
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev' => false,
),
'versions' => array(
'chillerlan/php-qrcode' => array(
'pretty_version' => '3.4.1',
'version' => '3.4.1.0',
'reference' => '468603b687a5fe75c1ff33857a45f1726c7b95a9',
'type' => 'library',
'install_path' => __DIR__ . '/../chillerlan/php-qrcode',
'aliases' => array(),
'dev_requirement' => false,
),
'chillerlan/php-settings-container' => array(
'pretty_version' => '1.2.2',
'version' => '1.2.2.0',
'reference' => 'd1b5284d6eb3a767459738bb0b20073f0cb3eeaf',
'type' => 'library',
'install_path' => __DIR__ . '/../chillerlan/php-settings-container',
'aliases' => array(),
'dev_requirement' => false,
),
'payeye/lib' => array(
'pretty_version' => '1.18.13',
'version' => '1.18.13.0',
'reference' => 'c00935223fd34c32116b6e5bd2907808cce8961d',
'type' => 'library',
'install_path' => __DIR__ . '/../payeye/lib',
'aliases' => array(),
'dev_requirement' => false,
),
'payeye/woocommerce' => array(
'pretty_version' => '1.0.0+no-version-set',
'version' => '1.0.0.0',
'reference' => NULL,
'type' => 'library',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
'dev_requirement' => false,
),
),
);

View File

@@ -0,0 +1,26 @@
<?php
// platform_check.php @generated by Composer
$issues = array();
if (!(PHP_VERSION_ID >= 70200)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
}
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
} elseif (!headers_sent()) {
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
}
}
trigger_error(
'Composer detected issues in your platform: ' . implode(' ', $issues),
E_USER_ERROR
);
}

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Auth;
class AuthConfig
{
/** @var string */
private $shopId;
/** @var string */
private $publicKey;
/** @var string */
private $privateKey;
public function __construct(string $shopId, string $publicKey, string $privateKey)
{
$this->shopId = $shopId;
$this->publicKey = $publicKey;
$this->privateKey = $privateKey;
}
public function getShopId(): string
{
return $this->shopId;
}
public function getPublicKey(): string
{
return $this->publicKey;
}
public function getPrivateKey(): string
{
return $this->privateKey;
}
}

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Auth;
class AuthRequest
{
/** @var array */
private $signatureFrom;
/** @var string */
private $signature;
public function __construct(array $signatureFrom, string $signature)
{
$this->signatureFrom = $signatureFrom;
$this->signature = $signature;
}
public static function createFromArray(array $context): self
{
return new self(
$context['signatureFrom'] ?? [],
$context['signature'] ?? ''
);
}
public function toArray(): array
{
return [
'signatureFrom' => $this->getSignatureFrom(),
'signature' => $this->getSignature(),
];
}
public function getSignatureFrom(): array
{
return $this->signatureFrom;
}
public function getSignature(): string
{
return $this->signature;
}
}

View File

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Auth;
use PayEye\Lib\Tool\JsonHelper;
class AuthService
{
/** @var HashService */
private $hashService;
/** @var array */
private $signatureFrom;
/** @var array */
private $payload;
public function __construct(HashService $hashService, array $signatureFrom, array $payload)
{
$this->hashService = $hashService;
$this->signatureFrom = $signatureFrom;
$this->payload = $payload;
}
public function getSignature(): string
{
return $this->hashService->hash($this->getJsonSignatureFrom());
}
public function getSignatureFrom(): array
{
return $this->signatureFrom;
}
public function getPayload(): array
{
return $this->payload;
}
private function getJsonSignatureFrom(): string
{
$data = [];
foreach ($this->signatureFrom as $key) {
$data[$key] = $this->payload[$key];
}
return JsonHelper::jsonEncode($data);
}
}

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Auth;
use PayEye\Lib\Model\Cart;
use PayEye\Lib\Model\Product;
use PayEye\Lib\Model\PromoCode;
use PayEye\Lib\Model\ShippingMethod;
use PayEye\Lib\Tool\JsonHelper;
class HashService
{
/** @var AuthConfig */
private $authConfig;
public function __construct(AuthConfig $authConfig)
{
$this->authConfig = $authConfig;
}
public function hash(string $json): string
{
return hash('sha256', $this->authConfig->getPrivateKey().$this->authConfig->getPublicKey().$json);
}
/**
* @param PromoCode[] $promoCodes
* @param ShippingMethod[] $shippingMethods
* @param Cart $cart
* @param Product[] $products
* @param string|null $shippingId
* @param string $currency
* @return string
*/
public function cartHash(
array $promoCodes,
array $shippingMethods,
Cart $cart,
?string $shippingId,
string $currency,
array $products
): string {
return $this->hash(JsonHelper::jsonEncode([$promoCodes, $shippingId, $shippingMethods, $cart, $currency, $products]));
}
}

View File

@@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Cart;
use PayEye\Lib\Model\Billing;
use PayEye\Lib\Model\Shipping;
class CartRequestModel
{
/** @var string */
private $cartId;
/** @var null|string */
private $shippingId;
/** @var null|Billing */
private $billing;
/** @var null|Shipping */
private $shipping;
/** @var null|string */
private $shippingProvider;
public function __construct(array $request)
{
$this->cartId = $request['cartId'];
$this->shippingId = $request['shippingId'] ?? null;
$billing = $request['billing'] ?? null;
if ($billing) {
$this->billing = new Billing($billing);
}
$this->shippingProvider = $request['shippingProvider'] ?? null;
$shipping = $request['shipping'] ?? null;
if ($shipping) {
$this->shipping = new Shipping($shipping);
}
}
public function getCartId(): string
{
return $this->cartId;
}
public function getShippingId(): ?string
{
return $this->shippingId;
}
public function getBilling(): ?Billing
{
return $this->billing;
}
public function getShippingProvider(): ?string
{
return $this->shippingProvider;
}
public function getShipping(): ?Shipping
{
return $this->shipping;
}
}

View File

@@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Cart;
use PayEye\Lib\Model\Cart;
use PayEye\Lib\Model\Product;
use PayEye\Lib\Model\PromoCode;
use PayEye\Lib\Model\ShippingMethod;
use PayEye\Lib\Model\Shop;
use PayEye\Lib\Tool\Builder;
class CartResponseModel
{
use Builder;
/** @var Shop */
public $shop;
/** @var PromoCode[] */
public $promoCodes;
/** @var string|null */
public $shippingId;
/** @var ShippingMethod[] */
public $shippingMethods;
/** @var Cart */
public $cart;
/** @var string */
public $currency;
/** @var Product[] */
public $products;
/** @var string */
public $cartHash;
/** @var string[] */
public $signatureFrom;
public static function createFromArray(array $context): self
{
$shippingMethods = array_map(static function (array $shipping) {
return ShippingMethod::createFromArray($shipping);
}, $context['shippingMethods']);
$products = array_map(static function (array $product) {
return Product::createFromArray($product);
}, $context['products']);
$promoCodes = array_map(static function (array $product) {
return PromoCode::createFromArray($product);
}, $context['promoCodes']);
return self::builder()
->setShop(Shop::createFromArray($context['shop']))
->setPromoCodes($promoCodes)
->setShippingId($context['shippingId'])
->setShippingMethods($shippingMethods)
->setCart(Cart::createFromArray($context['cart']))
->setCurrency($context['currency'])
->setProducts($products)
->setCartHash($context['cartHash'])
->setSignatureFrom($context['signatureFrom']);
}
public function setShop(Shop $shop): self
{
$this->shop = $shop;
return $this;
}
/**
* @param PromoCode[] $promoCodes
*/
public function setPromoCodes(array $promoCodes): self
{
$this->promoCodes = $promoCodes;
return $this;
}
public function setShippingId(?string $shippingId): self
{
$this->shippingId = $shippingId;
return $this;
}
/**
* @param ShippingMethod[] $shippingMethods
*/
public function setShippingMethods(array $shippingMethods): self
{
$this->shippingMethods = $shippingMethods;
return $this;
}
public function setCart(Cart $cart): self
{
$this->cart = $cart;
return $this;
}
public function setCurrency(string $currency): self
{
$this->currency = $currency;
return $this;
}
/**
* @param Product[] $products
*/
public function setProducts(array $products): self
{
$this->products = $products;
return $this;
}
public function setCartHash(string $cartHash): self
{
$this->cartHash = $cartHash;
return $this;
}
/**
* @param string[] $signatureFrom
*/
public function setSignatureFrom(array $signatureFrom): self
{
$this->signatureFrom = $signatureFrom;
return $this;
}
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Deeplink;
use PayEye\Lib\Auth\AuthConfig;
use PayEye\Lib\Env\Config;
class Deeplink
{
public static function create(Config $config, AuthConfig $authConfig, string $cartId): string
{
$query = [
'cartId' => $cartId,
'shopId' => $authConfig->getShopId(),
];
$query = http_build_query($query);
return $config->getDeepLinkUrl().'?'.$query;
}
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Enum;
abstract class ErrorCode
{
public const SIGNATURE_NOT_MATCHED = 'SIGNATURE_NOT_MATCHED';
public const CART_CONTENT_NOT_MATCHED = 'CART_CONTENT_NOT_MATCHED';
public const CART_NOT_FOUND = 'CART_NOT_FOUND';
public const CART_EMPTY = 'CART_EMPTY';
public const INVALID_COUPON = 'INVALID_COUPON';
public const INVALID_POST_CODE = 'INVALID_POST_CODE';
public const INVALID_PRODUCT_STOCK = 'INVALID_PRODUCT_STOCK';
public const APPLIED_COUPON = 'APPLIED_COUPON';
public const INVALID_SHIPPING = 'INVALID_SHIPPING';
public const ORDER_NOT_FOUND = 'ORDER_NOT_FOUND';
public const ORDER_ALREADY_EXISTS = 'ORDER_ALREADY_EXISTS';
public const ORDER_PAID = 'ORDER_PAID';
public const ORDER_FAILED = 'ORDER_FAILED';
public const SHOP_ID_NOT_MATCHED = 'SHOP_ID_NOT_MATCHED';
public const PAYEYE_PAYMENT_IS_DISABLED = 'PAYEYE_PAYMENT_IS_DISABLED';
public const SHIPPING_PROVIDER_NOT_MATCHED = 'SHIPPING_PROVIDER_NOT_MATCHED';
public const RETURN_NOT_FOUND = 'RETURN_NOT_FOUND';
public const WOOCOMMERCE = 'WOOCOMMERCE';
public const PRESTASHOP = 'PRESTASHOP';
public const Magento2 = 'MAGENTO2';
public const UNKNOWN = 'UNKNOWN';
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Enum;
abstract class HttpStatus
{
public const OK = 200;
public const BAD_REQUEST = 400;
public const UNAUTHORIZED = 401;
public const NOT_FOUND = 404;
public const INTERNAL_SERVER_ERROR = 500;
public const SERVICE_UNAVAILABLE = 503;
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Enum;
abstract class OrderStatus
{
public const SUCCESS = 'SUCCESS';
public const REJECTED = 'REJECTED';
public static function getAll(): array
{
return [
self::REJECTED,
self::SUCCESS,
];
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Enum;
abstract class PickupPointType
{
public const PARCEL_LOCKER = 'PARCEL_LOCKER';
public const PARCEL_POINT = 'PARCEL_POINT';
public const ZABKA = 'ZABKA';
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Enum;
abstract class PromoCodeType
{
public const CONSTANT_DISCOUNT_VALUE = 'CONSTANT_DISCOUNT_VALUE';
public const PERCENTAGE_DISCOUNT_VALUE = 'PERCENTAGE_DISCOUNT_VALUE';
public static function getAll(): array
{
return [
self::CONSTANT_DISCOUNT_VALUE,
self::PERCENTAGE_DISCOUNT_VALUE
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Enum;
abstract class ReturnStatus
{
public const CREATED = 'CREATED';
public const ACCEPTED = 'ACCEPTED';
public const REJECTED = 'REJECTED';
public static function getAll(): array
{
return [
self::CREATED,
self::ACCEPTED,
self::REJECTED,
];
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace PayEye\Lib\Enum;
abstract class ShippingProvider
{
public const INPOST = 'INPOST';
public const DHL = 'DHL';
public const COURIER = 'COURIER';
public const SELF_PICKUP = 'SELF_PICKUP';
public static function getAll(): array
{
return [
self::INPOST,
self::DHL,
self::COURIER,
self::SELF_PICKUP,
];
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace PayEye\Lib\Enum;
abstract class SignatureFrom
{
public const REFRESH_CART_REQUEST = ['cartId', 'shopIdentifier', 'eventType'];
public const GET_CART_RESPONSE = ['cart', 'products', 'currency', 'promoCodes', 'shippingMethods', 'shop', 'shippingId', 'cartHash'];
public const CART_COUPON_APPLY_RESPONSE = ['status'];
public const CART_COUPON_REMOVE_RESPONSE = ['status'];
public const VERIFY_KEYS_RESPONSE = ['status'];
public const CREATE_ORDER_RESPONSE = ['checkoutUrl', 'orderId', 'totalAmount', 'cartAmount', 'shippingAmount', 'currency'];
public const UPDATE_STATUS_ORDER_RESPONSE = ['status'];
public const HANDLE_ERROR = ['errorMessage', 'errorCode'];
public const RETURN_CREATE_RESPONSE = ['returnId', 'status'];
public const RETURN_STATUS_REQUEST = ['shopIdentifier', 'returnId', 'status', 'amount'];
public const UPDATE_STATUS_RETURN_RESPONSE = ['status'];
}

View File

@@ -0,0 +1,10 @@
<?php
namespace PayEye\Lib\Enum;
abstract class TransferStatus
{
public const SUCCESS = 'SUCCESS';
public const IN_PROGRESS = 'IN_PROGRESS';
public const REJECTED = 'REJECTED';
}

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Env;
use RuntimeException;
class Config
{
/** @var string */
private $url;
/** @var string */
private $deepLink;
/** @var self */
private static $instance;
public function __construct(string $url, string $deepLink)
{
$this->url = $url;
$this->deepLink = $deepLink;
self::$instance = $this;
}
public static function createFromArray(array $context): self
{
return new self(
$context['url'],
$context['deepLinkUrl']
);
}
public static function getInstance(): self
{
if (!self::$instance) {
throw new RuntimeException('Instance does not exist. Create this object onInit application.');
}
return self::$instance;
}
public function getUrl(): string
{
return $this->url;
}
public function getDeepLinkUrl(): string
{
return $this->deepLink;
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class CartContentNotMatchedException extends PayEyePaymentException
{
protected $message = 'Cart content not matched';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::CART_CONTENT_NOT_MATCHED;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class CartEmptyException extends PayEyePaymentException
{
protected $message = 'Cart is empty';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::CART_EMPTY;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class CartNotFoundException extends PayEyePaymentException
{
protected $message = 'Cart not found';
protected $statusCode = HttpStatus::NOT_FOUND;
protected $errorCode = ErrorCode::CART_NOT_FOUND;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class CouponAppliedException extends PayEyePaymentException
{
protected $message = 'Coupon Applied';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::APPLIED_COUPON;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class InvalidCartStockException extends PayEyePaymentException
{
protected $message = 'Product is not in stock';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::INVALID_PRODUCT_STOCK;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class InvalidCouponException extends PayEyePaymentException
{
protected $message = 'Invalid coupon';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::INVALID_COUPON;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class InvalidPostCodeException extends PayEyePaymentException
{
protected $message = 'Invalid post code';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::INVALID_POST_CODE;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class InvalidShippingException extends PayEyePaymentException
{
protected $message = 'Invalid shipping';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::INVALID_SHIPPING;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class OrderAlreadyExistsException extends PayEyePaymentException
{
protected $message = 'Order with cardId is already exists';
protected $statusCode = HttpStatus::NOT_FOUND;
protected $errorCode = ErrorCode::ORDER_ALREADY_EXISTS;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class OrderFailedException extends PayEyePaymentException
{
protected $message = 'Order has REJECTED status';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::ORDER_FAILED;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class OrderNotFoundException extends PayEyePaymentException
{
protected $message = 'Order not found';
protected $statusCode = HttpStatus::NOT_FOUND;
protected $errorCode = ErrorCode::ORDER_NOT_FOUND;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class OrderPaidException extends PayEyePaymentException
{
protected $message = 'Order is paid';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::ORDER_PAID;
}

View File

@@ -0,0 +1,12 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\HttpStatus;
class OrderPriceNotMatchedException extends PayEyePaymentException
{
protected $message = 'Order price not matched';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = 'ORDER_PRICE_NOT_MATCHED';
}

View File

@@ -0,0 +1,24 @@
<?php
namespace PayEye\Lib\Exception;
use Exception;
class PayEyePaymentException extends Exception
{
/** @var $statusCode int */
protected $statusCode;
/** @var $errorCode string */
protected $errorCode;
public function getStatusCode(): int
{
return $this->statusCode;
}
public function getErrorCode(): string
{
return $this->errorCode;
}
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class PaymentMethodIsDisabledException extends PayEyePaymentException
{
protected $message = 'Payment method is disabled';
protected $statusCode = HttpStatus::BAD_REQUEST;
protected $errorCode = ErrorCode::PAYEYE_PAYMENT_IS_DISABLED;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace PayEye\Lib\Exception;
use PayEye\Lib\Enum\ErrorCode;
use PayEye\Lib\Enum\HttpStatus;
class ReturnNotFoundException extends PayEyePaymentException
{
protected $message = 'Return not found';
protected $statusCode = HttpStatus::NOT_FOUND;
protected $errorCode = ErrorCode::RETURN_NOT_FOUND;
}

Some files were not shown because too many files have changed in this diff Show More