diff --git a/README.md b/README.md
index 8b43ea3..a174555 100644
--- a/README.md
+++ b/README.md
@@ -1,36 +1,38 @@
-
-# KEKS Pay for WooCommerce.
-
-KEKS Pay for WooCommerce offers you a simple and seamless way of taking KEKS Pay payments. Your customers will have the best time saving user experience in the checkout process - especially while buying on smartphones. It will increase your conversion-rate and the likeliness to return to your shop. On the other hand, via KEKS Pay you will be able to accept VISA, Mastercard, Maestro or Diners Club cards and payments directly from your customer's bank account.
-
-Currently KEKS Pay for WooCommerce is available for merchants only in CROATIA.
-
-## Why choose KEKS Pay?
-
-KEKS Pay has no setup fees, no monthly fees, no hidden costs - you only get charged when you take payments through KEKS Pay. Earnings are transferred to your bank account on a 1-day rolling basis.
-
-Cancel whenever you want without additional costs.
-
-## How to refund a KEKS Pay payment?
-
-To do a refund, select the order and click the Refund button afterward. You will be able to type in the amount you would refund. The order status will change to “Refunded” once the order has been successfully refunded.
-
-On a side note, this plugin is provided “as-is” and we don't currently provide support around installing and optimizing it for your needs.
-
-## Installation
-#### MINIMUM REQUIREMENTS
-
-* WooCommerce 3.3 or greater.
-* WordPress 5.0 or greater.
-* PHP version 7.2 or greater.
-* SSL must be installed on your site and active on your Checkout pages.
-
-#### INSTALL
-
-1. Contact ERSTE KEKS Pay team and set up your merchant account.
-2. Visit Plugins > Add New.
-3. Search for "KEKS Pay for WooCommerce".
-4. Install and activate KEKS Pay for WooCommerce plugin.
-5. Visit plugin settings and fill in merchant info you received from ERSTE KEKS Pay team.
-
-For more installation options check the [official WordPress documentation](https://wordpress.org/support/article/managing-plugins/#manual-plugin-installation) about installing plugins.
\ No newline at end of file
+
+# KEKS Pay for WooCommerce.
+
+KEKS Pay for WooCommerce offers you a simple and seamless way of taking KEKS Pay payments. Your customers will have the best time saving user experience in the checkout process - especially while buying on smartphones. It will increase your conversion-rate and the likeliness to return to your shop. On the other hand, via KEKS Pay you will be able to accept VISA, Mastercard, Maestro or Diners Club cards and payments directly from your customer's bank account.
+
+Currently KEKS Pay for WooCommerce is available for merchants only in CROATIA.
+
+## Why choose KEKS Pay?
+
+KEKS Pay has no setup fees, no monthly fees, no hidden costs - you only get charged when you take payments through KEKS Pay. Earnings are transferred to your bank account on a 1-day rolling basis.
+
+Cancel whenever you want without additional costs.
+
+## How to refund a KEKS Pay payment?
+
+To do a refund, select the order and click the Refund button afterward. You will be able to type in the amount you would refund. The order status will change to “Refunded” once the order has been successfully refunded.
+
+On a side note, this plugin is provided “as-is” and we don't currently provide support around installing and optimizing it for your needs.
+
+## Installation
+#### MINIMUM REQUIREMENTS
+
+* WooCommerce 8.2 or greater.
+* WordPress 6.3 or greater.
+* PHP version 7.4 or greater.
+* SSL must be installed on your site and active on your Checkout pages.
+
+#### INSTALL
+
+1. Contact ERSTE KEKS Pay team and set up your merchant account.
+2. Visit Plugins > Add New.
+3. Search for "KEKS Pay for WooCommerce".
+4. Install and activate KEKS Pay for WooCommerce plugin.
+5. Visit plugin settings and fill in merchant info you received from ERSTE KEKS Pay team.
+
+For more installation options check the [official WordPress documentation](https://wordpress.org/support/article/managing-plugins/#manual-plugin-installation) about installing plugins.
+
+
diff --git a/composer.json b/composer.json
index 98544bc..3202714 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"require": {
- "php": "^7.2",
- "chillerlan/php-qrcode": "^3.4"
+ "php": "^7.4 || ^8.0",
+ "chillerlan/php-qrcode": "^4.4"
}
}
diff --git a/composer.lock b/composer.lock
index 9301ab9..c036f9e 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,34 +4,38 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e0028656b355389d2aff60386255d921",
+ "content-hash": "54b2a951672c3176ad97ff12e9896034",
"packages": [
{
"name": "chillerlan/php-qrcode",
- "version": "3.4.0",
+ "version": "4.4.1",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-qrcode.git",
- "reference": "d8bf297e6843a53aeaa8f3285ce04fc349d133d6"
+ "reference": "f5e243f3b61a60934780579430a951460f40888d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/d8bf297e6843a53aeaa8f3285ce04fc349d133d6",
- "reference": "d8bf297e6843a53aeaa8f3285ce04fc349d133d6",
+ "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/f5e243f3b61a60934780579430a951460f40888d",
+ "reference": "f5e243f3b61a60934780579430a951460f40888d",
"shasum": ""
},
"require": {
- "chillerlan/php-settings-container": "^1.2",
+ "chillerlan/php-settings-container": "^2.1.4 || ^3.1",
"ext-mbstring": "*",
- "php": "^7.2"
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
- "phpunit/phpunit": "^8.5",
- "setasign/fpdf": "^1.8.2"
+ "phan/phan": "^5.4",
+ "phpmd/phpmd": "^2.15",
+ "phpunit/phpunit": "^9.6",
+ "setasign/fpdf": "^1.8.2",
+ "squizlabs/php_codesniffer": "^3.8"
},
"suggest": {
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
- "setasign/fpdf": "Required to use the QR FPDF output."
+ "setasign/fpdf": "Required to use the QR FPDF output.",
+ "simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code"
},
"type": "library",
"autoload": {
@@ -58,7 +62,7 @@
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
}
],
- "description": "A QR code generator. PHP 7.2+",
+ "description": "A QR code generator with a user friendly API. PHP 7.4+",
"homepage": "https://github.com/chillerlan/php-qrcode",
"keywords": [
"phpqrcode",
@@ -67,28 +71,45 @@
"qrcode",
"qrcode-generator"
],
- "time": "2020-11-18T20:51:41+00:00"
+ "support": {
+ "issues": "https://github.com/chillerlan/php-qrcode/issues",
+ "source": "https://github.com/chillerlan/php-qrcode/tree/4.4.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4",
+ "type": "custom"
+ },
+ {
+ "url": "https://ko-fi.com/codemasher",
+ "type": "ko_fi"
+ }
+ ],
+ "time": "2024-01-06T16:56:58+00:00"
},
{
"name": "chillerlan/php-settings-container",
- "version": "1.2.1",
+ "version": "2.1.5",
"source": {
"type": "git",
"url": "https://github.com/chillerlan/php-settings-container.git",
- "reference": "b9b0431dffd74102ee92348a63b4c33fc8ba639b"
+ "reference": "f705310389264c3578fdd9ffb15aa2cd6d91772e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/b9b0431dffd74102ee92348a63b4c33fc8ba639b",
- "reference": "b9b0431dffd74102ee92348a63b4c33fc8ba639b",
+ "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/f705310389264c3578fdd9ffb15aa2cd6d91772e",
+ "reference": "f705310389264c3578fdd9ffb15aa2cd6d91772e",
"shasum": ""
},
"require": {
"ext-json": "*",
- "php": "^7.2"
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
- "phpunit/phpunit": "^8.3"
+ "phan/phan": "^5.4",
+ "phpcsstandards/php_codesniffer": "^3.8",
+ "phpmd/phpmd": "^2.13",
+ "phpunit/phpunit": "^9.6"
},
"type": "library",
"autoload": {
@@ -107,15 +128,30 @@
"homepage": "https://github.com/codemasher"
}
],
- "description": "A container class for immutable settings objects. Not a DI container. PHP 7.2+",
+ "description": "A container class for immutable settings objects. Not a DI container. PHP 7.4+",
"homepage": "https://github.com/chillerlan/php-settings-container",
"keywords": [
"PHP7",
"Settings",
+ "configuration",
"container",
"helper"
],
- "time": "2019-09-10T00:09:44+00:00"
+ "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"
+ }
+ ],
+ "time": "2024-01-05T23:20:55+00:00"
}
],
"packages-dev": [],
@@ -125,7 +161,8 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": "^7.2"
+ "php": "^7.4 || ^8.0"
},
- "platform-dev": []
+ "platform-dev": [],
+ "plugin-api-version": "2.0.0"
}
diff --git a/includes/core/class-kekspay-connector.php b/includes/core/class-kekspay-connector.php
index 9b47543..5959795 100644
--- a/includes/core/class-kekspay-connector.php
+++ b/includes/core/class-kekspay-connector.php
@@ -1,134 +1,128 @@
array(
- 'Content-Type' => 'application/json',
- ),
- 'method' => 'POST',
- 'timeout' => 55,
- 'body' => $encoded_body,
- 'cookies' => [],
- );
- }
-
- /**
- * Trigger refund for given order and amount.
- *
- * @param WC_Order $order
- * @param float $amount
- *
- * @return array [ 'success' => bool, 'message' => string ]
- */
- public function refund( $order, $amount ) {
- if ( 'erste-kekspay-woocommerce' !== $order->get_payment_method() ) {
- return;
- }
-
- $currency = $order->get_currency();
-
- $refund_amount = $amount;
- $refund_currency = $currency;
-
- if ( 'HRK' === $currency ) {
- $refund_amount = round( $amount / 7.5345, 2 );
- $refund_currency = 'EUR';
- }
-
- $timestamp = time();
-
- $hash = Kekspay_Data::get_hash( $order, $refund_amount, $timestamp );
- if ( ! $hash ) {
- return false;
- }
-
- $body = array(
- 'bill_id' => Kekspay_Data::get_bill_id_by_order_id( $order->get_id() ),
- 'tid' => Kekspay_Data::get_settings( 'webshop-tid', true ),
- 'cid' => Kekspay_Data::get_settings( 'webshop-cid', true ),
- 'amount' => $refund_amount,
- 'epochtime' => $timestamp,
- 'hash' => $hash,
- 'algo' => Kekspay_Data::get_algo(),
- 'currency' => $refund_currency,
- );
-
- $wc_price = wc_price( $amount, array( 'currency' => $currency ) );
-
- $response = wp_safe_remote_post( Kekspay_Data::get_kekspay_api_base() . 'keksrefund', $this->get_default_args( $body ) );
- Kekspay_Logger::log( 'Request sent to refund order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay.', 'info' );
-
- if ( is_wp_error( $response ) ) {
- Kekspay_Logger::log( $response->get_error_message(), 'error' );
- return false;
- }
-
- $status_code = wp_remote_retrieve_response_code( $response );
- if ( $status_code < 200 || $status_code > 299 ) {
- Kekspay_Logger::log( 'Refund for order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay failed, does not have a success status code.', 'error' );
- return false;
- }
-
- $refund = wp_remote_retrieve_body( $response );
- if ( ! $refund ) {
- Kekspay_Logger::log( 'Refund for order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay failed, body corrupted or missing.', 'error' );
- return false;
- }
-
- // Log response from refund request.
- Kekspay_Logger::log( $refund, 'info' );
-
- $response_data = json_decode( $refund );
-
- if ( isset( $response_data->status ) && 0 === $response_data->status ) {
- $note = sprintf( __( 'Uspješno izvršen povrat %s via KEKS Pay.', 'kekspay' ), $wc_price );
- Kekspay_Logger::log( 'Successfully refunded order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay. Setting status refunded.', 'info' );
- $order->add_order_note( $note );
- $order->update_meta_data( 'kekspay_status', (int) $order->get_remaining_refund_amount() ? 'refunded_partially' : 'refunded' );
- $order->save();
-
- return true;
- } else {
- $note = sprintf( __( 'Dogodila se greška pri povratu %s via KEKS Pay.', 'kekspay' ), $wc_price );
- $message = isset( $response_data->message ) ? $response_data->message : '';
- Kekspay_Logger::log( 'Failed to refund order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay. Message: ' . $message, 'error' );
- $order->add_order_note( $note );
- $order->save();
-
- return false;
- }
- }
- }
+/**
+ * Kekspay_Connector class
+ *
+ * @since 0.1
+ */
+class Kekspay_Connector {
+
+ /**
+ * Return an array for default args or false if failed to JSON encode.
+ *
+ * @param array $body
+ * @return array|false
+ */
+ private static function get_default_args( $body ) {
+ $encoded_body = wp_json_encode( $body );
+
+ if ( ! $encoded_body ) {
+ return false;
+ }
+
+ // Log body data for refund request.
+ Kekspay_Logger::log( $encoded_body, 'info' );
+
+ return [
+ 'headers' => [
+ 'Content-Type' => 'application/json',
+ ],
+ 'method' => 'POST',
+ 'timeout' => 55,
+ 'body' => $encoded_body,
+ 'cookies' => [],
+ ];
+ }
+
+ /**
+ * Trigger refund for given order and amount.
+ *
+ * @param WC_Order $order
+ * @param float $amount
+ *
+ * @return array [ 'success' => bool, 'message' => string ]
+ */
+ public static function refund( $order, $amount ) {
+ if ( 'erste-kekspay-woocommerce' !== $order->get_payment_method() ) {
+ return;
+ }
+
+ $currency = $order->get_currency();
+
+ $refund_amount = $amount;
+ $refund_currency = $currency;
+
+ if ( 'HRK' === $currency ) {
+ $refund_amount = round( $amount / 7.5345, 2 );
+ $refund_currency = 'EUR';
+ }
+
+ $timestamp = time();
+
+ $hash = Kekspay_Data::get_hash( $order, $refund_amount, $timestamp );
+ if ( ! $hash ) {
+ return false;
+ }
+
+ $body = [
+ 'bill_id' => Kekspay_Data::get_bill_id_by_order_id( $order->get_id() ),
+ 'tid' => Kekspay_Data::get_settings( 'webshop-tid', true ),
+ 'cid' => Kekspay_Data::get_settings( 'webshop-cid', true ),
+ 'amount' => $refund_amount,
+ 'epochtime' => $timestamp,
+ 'hash' => $hash,
+ 'algo' => Kekspay_Data::get_algo(),
+ 'currency' => $refund_currency,
+ ];
+
+ $wc_price = wc_price( $amount, [ 'currency' => $currency ] );
+
+ $response = wp_safe_remote_post( Kekspay_Data::get_kekspay_api_base() . 'keksrefund', self::get_default_args( $body ) );
+ Kekspay_Logger::log( 'Request sent to refund order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay.', 'info' );
+
+ if ( is_wp_error( $response ) ) {
+ Kekspay_Logger::log( $response->get_error_message(), 'error' );
+ return false;
+ }
+
+ $status_code = wp_remote_retrieve_response_code( $response );
+ if ( $status_code < 200 || $status_code > 299 ) {
+ Kekspay_Logger::log( 'Refund for order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay failed, does not have a success status code.', 'error' );
+ return false;
+ }
+
+ $refund = wp_remote_retrieve_body( $response );
+ if ( ! $refund ) {
+ Kekspay_Logger::log( 'Refund for order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay failed, body corrupted or missing.', 'error' );
+ return false;
+ }
+
+ // Log response from refund request.
+ Kekspay_Logger::log( $refund, 'info' );
+
+ $response_data = json_decode( $refund );
+
+ if ( isset( $response_data->status ) && 0 === $response_data->status ) {
+ /* translators: successful refund */
+ $note = sprintf( __( 'Uspješno izvršen povrat %s via KEKS Pay.', 'kekspay' ), $wc_price );
+ Kekspay_Logger::log( 'Successfully refunded order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay. Setting status refunded.', 'info' );
+ $order->add_order_note( $note );
+ $order->update_meta_data( 'kekspay_status', (int) $order->get_remaining_refund_amount() ? 'refunded_partially' : 'refunded' );
+ $order->save();
+
+ return true;
+ } else {
+ /* translators: failed refund */
+ $note = sprintf( __( 'Dogodila se greška pri povratu %s via KEKS Pay.', 'kekspay' ), $wc_price );
+ $message = isset( $response_data->message ) ? $response_data->message : '';
+ Kekspay_Logger::log( 'Failed to refund order ' . $order->get_id() . ' (' . $amount . $order->get_currency() . ') via KEKS Pay. Message: ' . $message, 'error' );
+ $order->add_order_note( $note );
+ $order->save();
+
+ return false;
+ }
+ }
}
diff --git a/includes/core/class-kekspay-ipn.php b/includes/core/class-kekspay-ipn.php
index ff5afdc..2286b6b 100644
--- a/includes/core/class-kekspay-ipn.php
+++ b/includes/core/class-kekspay-ipn.php
@@ -1,204 +1,205 @@
-1,
- 'message' => $message,
- )
- );
-
- if ( ! $encoded_message ) {
- Kekspay_Logger::log( 'Failed to encode API response message.', 'error' );
- $encoded_message = -1;
- }
-
- wp_die( $encoded_message );
- }
-
- /**
- * Return assoc array of parameters from either 'php://input' (POST request body), or $_REQUEST.
- *
- * @return array $params
- */
- private function resolve_params() {
- $params = json_decode( file_get_contents( 'php://input' ), true );
- if ( empty( $params ) ) {
- // NOTE: external request, signature is checked in the calling method to determine validity.
- // phpcs:disable WordPress.Security.NonceVerification.Recommended
- $params = $_REQUEST;
- // phpcs:enable
- }
-
- if ( ! $params ) {
- return false;
- }
-
- return array_map(
- function( $item ) {
- return filter_var( $item, FILTER_SANITIZE_STRING );
- },
- $params
- );
- }
-
- /**
- * Check if order status has changed and return the new status
- *
- * @return void
- */
- public function kekspay_status_check() {
- check_ajax_referer( 'kekspay_advice_status' );
-
- $order = new WC_Order( filter_input( INPUT_POST, 'order_id', FILTER_SANITIZE_NUMBER_INT ) );
- $status = $order->get_meta( 'kekspay_status' );
-
- $response = array(
- 'status' => $status,
- 'redirect' => null,
- );
-
- if ( 'failed' === $status ) {
- wc_add_notice( sprintf( __( 'Nešto je pošlo po zlu pri pokušaju naplate vaše narudžbe (#%d) putem KEKS Pay servisa, molimo pokušajte ponoviti narudžbu ili kontaktirajte administratora web trgovine za više informacija.' ), $order->get_id() ), 'error' );
- $response['redirect'] = $order->get_cancel_order_url_raw();
- } elseif ( 'success' === $status ) {
- $response['redirect'] = $order->get_checkout_order_received_url();
- }
-
- $this->respond( $response );
- }
-
- /**
- * Should be used as a callback URL for KEKS Pay API checkout request.
- */
- public function do_checkout_status() {
- // Verify token authorization.
- if ( ! $this->verify_kekspay_token() ) {
- Kekspay_Logger::log( 'Failed to verify token.', 'error' );
- $this->respond_error( 'Webshop authentication failed, token mismatch.' );
- }
-
- $params = $this->resolve_params();
- Kekspay_Logger::log( wp_json_encode( $params ), 'info' );
- // Check if any parametars are received.
- if ( ! $params ) {
- Kekspay_Logger::log( 'Missing parameters in the request for IPN.', 'error' );
- $this->respond_error( 'Missing parameters.' );
- }
-
- // Check if required params are recieved.
- foreach ( array( 'bill_id', 'status', 'keks_id', 'tid' ) as $required_param ) {
- if ( ! isset( $params[ $required_param ] ) ) {
- Kekspay_Logger::log( 'Missing ' . $required_param . ' parametar in the request for IPN.', 'error' );
- $this->respond_error( 'Missing or corrupt required parametars.' );
- }
- }
-
- // Check if recieved TID matches the webshop TID.
- if ( $params['tid'] !== Kekspay_Data::get_settings( 'webshop-tid', true ) ) {
- Kekspay_Logger::log( 'Recieved TID ' . $params['tid'] . ' does not match webshop TID in the request for IPN.', 'error' );
- $this->respond_error( 'Webshop verification failed, mismatch for TID ' . $params['tid'] . '.' );
- }
-
- // Extract order id and check if order exists.
- $order_id = Kekspay_Data::get_order_id_by_bill_id( $params['bill_id'] );
- $order = wc_get_order( $order_id );
- if ( ! $order ) {
- Kekspay_Logger::log( 'Failed to find order ' . $params['bill_id'] . ' from the request for IPN.', 'error' );
- $this->respond_error( 'Couldn\'t find corresponding order ' . $params['bill_id'] . '.' );
- }
-
- if ( (int) $params['status'] === 0 ) {
- Kekspay_Logger::log( 'KEKS Pay successfully completed payment for order ' . $order_id . ', setting status to ' . $params['message'], 'info' );
- $order->set_status( Kekspay_Data::get_settings( 'payed-order-status' ) ?: 'processing', __( 'Narudžba uspješno plaćena putem KEKS Pay aplikacije.', 'kekspay' ) ); //phpcs:ignore
- $order->add_meta_data( 'kekspay_status', 'success', true );
- $order->add_meta_data( 'kekspay_id', $params['keks_id'], true );
- $order->save();
- } else {
- Kekspay_Logger::log( 'KEKS Pay failed to complete payment for order ' . $order_id . ', message: ' . $params['message'], 'error' );
- $order->add_meta_data( 'kekspay_status', 'failed', true );
- $order->add_order_note( __( 'Dogodila se greška pri naplati putem KEKS Pay aplikacije.', 'kekspay' ) );
- $order->save();
- }
-
- $this->respond(
- array(
- 'status' => 0,
- 'message' => 'Accepted',
- )
- );
- }
-
- /**
- * Compares tokens to verify valid request.
- *
- * @return bool
- */
- private function verify_kekspay_token() {
- $token_src = 'REQUEST';
- $token = isset( $_REQUEST['token'] ) ? filter_var( wp_unslash( $_REQUEST['token'] ), FILTER_SANITIZE_STRING ) : false;
- if ( ! $token ) { // Legacy check.
- $token_src = 'REQUEST';
- $token = isset( $_SERVER['HTTP_AUTHORIZATION'] ) ? filter_var( $_SERVER['HTTP_AUTHORIZATION'], FILTER_SANITIZE_STRING ) : false;
- }
- if ( ! $token ) {
- Kekspay_Logger::log( 'Failed to recieve authentication token.', 'error' );
- $this->respond_error( 'Authentication token missing, failed to verify.' );
- } else {
- Kekspay_Logger::log( 'Token src: ' . $token_src, 'info' );
- }
-
- return hash_equals( Kekspay_Data::get_settings( 'auth-token' ), str_replace( 'Token ', '', $token ) );
- }
- }
+ /**
+ * Kekspay_IPN class
+ *
+ * @since 0.1
+ */
+ class Kekspay_IPN {
+
+ /**
+ * Class constructor.
+ */
+ public function __construct() {
+ add_action( 'woocommerce_api_' . Kekspay_Data::get_wc_endpoint(), [ $this, 'do_checkout_status' ] );
+ add_action( 'wp_ajax_kekspay_status_check', [ $this, 'kekspay_status_check' ] );
+ add_action( 'wp_ajax_nopriv_kekspay_status_check', [ $this, 'kekspay_status_check' ] );
+ }
+
+ /**
+ * Die with given message, encoded as JSON, and set HTTP response status.
+ *
+ * @param mixed $message
+ * @param integer $status_code Defaults to 200.
+ */
+ private function respond( $message, $status_code = 200 ) {
+ status_header( $status_code );
+ header( 'content-type: application/json; charset=utf-8' );
+
+ $encoded_message = wp_json_encode( $message );
+
+ if ( ! $encoded_message ) {
+ Kekspay_Logger::log( 'Failed to encode API response message.', 'error' );
+ $encoded_message = -1;
+ }
+
+ die( $encoded_message ); //@codingStandardsIgnoreLine - escaping not needed
+ }
+
+ /**
+ * Die with error and given message, encoded as JSON, and set HTTP response status.
+ *
+ * @param string $message Message description about the failure of request.
+ */
+ private function respond_error( $message ) {
+ status_header( 400 );
+ header( 'content-type: application/json; charset=utf-8' );
+
+ $encoded_message = wp_json_encode(
+ [
+ 'status' => -1,
+ 'message' => $message,
+ ]
+ );
+
+ if ( ! $encoded_message ) {
+ Kekspay_Logger::log( 'Failed to encode API response message.', 'error' );
+ $encoded_message = -1;
+ }
+
+ die( $encoded_message ); //@codingStandardsIgnoreLine - escaping not needed
+ }
+
+ /**
+ * Return assoc array of parameters from either 'php://input' (POST request body), or $_REQUEST.
+ *
+ * @return array $params
+ */
+ private function resolve_params() {
+ $params = json_decode( file_get_contents( 'php://input' ), true );
+ if ( empty( $params ) ) {
+ // NOTE: external request, signature is checked in the calling method to determine validity.
+ // phpcs:disable WordPress.Security.NonceVerification.Recommended
+ $params = $_REQUEST;
+ // phpcs:enable
+ }
+
+ if ( ! $params ) {
+ return false;
+ }
+
+ return array_map(
+ function( $item ) {
+ return filter_var( $item, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
+ },
+ $params
+ );
+ }
+
+ /**
+ * Check if order status has changed and return the new status
+ *
+ * @return void
+ */
+ public function kekspay_status_check() {
+ check_ajax_referer( 'kekspay_advice_status' );
+
+ $order = new WC_Order( filter_input( INPUT_POST, 'order_id', FILTER_SANITIZE_NUMBER_INT ) );
+ $status = $order->get_meta( 'kekspay_status' );
+
+ $response = [
+ 'status' => $status,
+ 'redirect' => null,
+ ];
+
+ if ( 'failed' === $status ) {
+ /* translators: payment failed on checkout QR scanning */
+ wc_add_notice( sprintf( __( 'Nešto je pošlo po zlu pri pokušaju naplate vaše narudžbe (#%d) putem KEKS Pay servisa, molimo pokušajte ponoviti narudžbu ili kontaktirajte administratora web trgovine za više informacija.' ), $order->get_id() ), 'error' );
+ $response['redirect'] = $order->get_cancel_order_url_raw();
+ } elseif ( 'success' === $status ) {
+ $response['redirect'] = $order->get_checkout_order_received_url();
+ }
+
+ $this->respond( $response );
+ }
+
+ /**
+ * Should be used as a callback URL for KEKS Pay API checkout request.
+ */
+ public function do_checkout_status() {
+ // Verify token authorization.
+ if ( ! $this->verify_kekspay_token() ) {
+ Kekspay_Logger::log( 'Failed to verify token.', 'error' );
+ $this->respond_error( 'Webshop authentication failed, token mismatch.' );
+ }
+
+ $params = $this->resolve_params();
+ Kekspay_Logger::log( wp_json_encode( $params ), 'info' );
+ // Check if any parametars are received.
+ if ( ! $params ) {
+ Kekspay_Logger::log( 'Missing parameters in the request for IPN.', 'error' );
+ $this->respond_error( 'Missing parameters.' );
+ }
+
+ // Check if required params are recieved.
+ foreach ( [ 'bill_id', 'status', 'keks_id', 'tid' ] as $required_param ) {
+ if ( ! isset( $params[ $required_param ] ) ) {
+ Kekspay_Logger::log( 'Missing ' . $required_param . ' parametar in the request for IPN.', 'error' );
+ $this->respond_error( 'Missing or corrupt required parametars.' );
+ }
+ }
+
+ // Check if recieved TID matches the webshop TID.
+ if ( $params['tid'] !== Kekspay_Data::get_settings( 'webshop-tid', true ) ) {
+ Kekspay_Logger::log( 'Recieved TID ' . $params['tid'] . ' does not match webshop TID in the request for IPN.', 'error' );
+ $this->respond_error( 'Webshop verification failed, mismatch for TID ' . $params['tid'] . '.' );
+ }
+
+ // Extract order id and check if order exists.
+ $order_id = Kekspay_Data::get_order_id_by_bill_id( $params['bill_id'] );
+ $order = wc_get_order( $order_id );
+ if ( ! $order ) {
+ Kekspay_Logger::log( 'Failed to find order ' . $params['bill_id'] . ' from the request for IPN.', 'error' );
+ $this->respond_error( 'Couldn\'t find corresponding order ' . $params['bill_id'] . '.' );
+ }
+
+ if ( (int) $params['status'] === 0 ) {
+ Kekspay_Logger::log( 'KEKS Pay successfully completed payment for order ' . $order_id . ', setting status to ' . $params['message'], 'info' );
+ $order->set_status( Kekspay_Data::get_settings( 'payed-order-status' ) ?: 'processing', __( 'Narudžba uspješno plaćena putem KEKS Pay aplikacije.', 'kekspay' ) );
+ $order->add_meta_data( 'kekspay_status', 'success', true );
+ $order->add_meta_data( 'kekspay_id', $params['keks_id'], true );
+ $order->save();
+ } else {
+ Kekspay_Logger::log( 'KEKS Pay failed to complete payment for order ' . $order_id . ', message: ' . $params['message'], 'error' );
+ $order->add_meta_data( 'kekspay_status', 'failed', true );
+ $order->add_order_note( __( 'Dogodila se greška pri naplati putem KEKS Pay aplikacije.', 'kekspay' ) );
+ $order->save();
+ }
+
+ $this->respond(
+ [
+ 'status' => 0,
+ 'message' => 'Accepted',
+ ]
+ );
+ }
+
+ /**
+ * Compares tokens to verify valid request.
+ *
+ * @return bool
+ */
+ private function verify_kekspay_token() {
+ $token_src = 'REQUEST';
+ $token = isset( $_REQUEST['token'] ) ? filter_var( wp_unslash( $_REQUEST['token'] ), FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : false; //@codingStandardsIgnoreLine - safe use of REQUEST.
+ if ( ! $token ) { // Legacy check.
+ $token_src = 'SERVER';
+ $token = isset( $_SERVER['HTTP_AUTHORIZATION'] ) ? filter_var( $_SERVER['HTTP_AUTHORIZATION'], FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : false; //@codingStandardsIgnoreLine - safe use of SERVER.
+ }
+ if ( ! $token ) {
+ Kekspay_Logger::log( 'Failed to recieve authentication token.', 'error' );
+ $this->respond_error( 'Authentication token missing, failed to verify.' );
+ } else {
+ Kekspay_Logger::log( 'Token src: ' . $token_src, 'info' );
+ }
+
+ return hash_equals( Kekspay_Data::get_settings( 'auth-token' ), str_replace( 'Token ', '', $token ) );
+ }
+ }
}
new Kekspay_IPN();
diff --git a/includes/core/class-kekspay-order-admin.php b/includes/core/class-kekspay-order-admin.php
index dcac938..7cb9237 100644
--- a/includes/core/class-kekspay-order-admin.php
+++ b/includes/core/class-kekspay-order-admin.php
@@ -1,58 +1,58 @@
base && 'shop_order' === $screen->id ) {
- $order = wc_get_order( get_the_ID() );
- if ( ! is_a( $order, 'WC_Order' ) ) {
- return;
- }
-
- if ( Kekspay_Data::order_test_mode( $order ) ) {
- $class = 'notice notice-warning';
- $message = __( 'Narudžba kreirana koristeći KEKS Pay u testnom načinu rada.', 'kekspay' );
-
- printf( '
', esc_attr( $class ), esc_html( $message ) );
- }
-
- if ( 'HRK' === $order->get_currency() ) {
- $class = 'notice notice-warning';
- $message = __( 'KEKS Pay - Narudžba naplaćena u valuti HRK koja više nije podržana od strane KEKS Pay sustava. Ako želite napraviti povrat novca kroz KEKS Pay sustav, iznos za povrat prije povrata preračunati će se u EUR prema tečaju 7.5345 te biti vraćen u valuti EUR.', 'kekspay' );
-
- printf( '', esc_attr( $class ), esc_html( $message ) );
- }
- }
-
- }
-
- }
+ /**
+ * Kekspay_Order_Admin class
+ *
+ * @since 0.1
+ */
+ class Kekspay_Order_Admin {
+
+ /**
+ * Class constructor.
+ */
+ public function __construct() {
+ add_action( 'admin_notices', [ $this, 'display_test_order_notice' ], 100 );
+ }
+
+ /**
+ * Display WordPress warning notice if current order (admin view) is processed in sandbox/test mode.
+ *
+ * @return void
+ */
+ public function display_test_order_notice() {
+ if ( ! is_admin() ) {
+ return;
+ }
+
+ $screen = get_current_screen();
+ if ( 'post' === $screen->base && 'shop_order' === $screen->id ) {
+ $order = wc_get_order( get_the_ID() );
+ if ( ! is_a( $order, 'WC_Order' ) ) {
+ return;
+ }
+
+ if ( Kekspay_Data::order_test_mode( $order ) ) {
+ $class = 'notice notice-warning';
+ $message = __( 'Narudžba kreirana koristeći KEKS Pay u testnom načinu rada.', 'kekspay' );
+
+ printf( '', esc_attr( $class ), esc_html( $message ) );
+ }
+
+ if ( 'HRK' === $order->get_currency() ) {
+ $class = 'notice notice-warning';
+ $message = __( 'KEKS Pay - Narudžba naplaćena u valuti HRK koja više nije podržana od strane KEKS Pay sustava. Ako želite napraviti povrat novca kroz KEKS Pay sustav, iznos za povrat prije povrata preračunati će se u EUR prema tečaju 7.5345 te biti vraćen u valuti EUR.', 'kekspay' );
+
+ printf( '', esc_attr( $class ), esc_html( $message ) );
+ }
+ }
+
+ }
+
+ }
}
new Kekspay_Order_Admin();
diff --git a/includes/core/class-kekspay-payment-gateway.php b/includes/core/class-kekspay-payment-gateway.php
index 0201d18..6b3ab65 100644
--- a/includes/core/class-kekspay-payment-gateway.php
+++ b/includes/core/class-kekspay-payment-gateway.php
@@ -1,224 +1,221 @@
id = KEKSPAY_PLUGIN_ID;
- $this->method_title = __( 'KEKS Pay', 'kekspay' );
- $this->method_description = __( 'Najbrže i bez naknada putem KEKS Pay aplikacije!', 'kekspay' );
- $this->has_fields = true;
-
- $this->init_form_fields();
- $this->init_settings();
-
- $this->supports = array( 'products', 'refunds' );
-
- $this->connector = new Kekspay_Connector();
- $this->sell = new Kekspay_Sell();
-
- $this->title = esc_attr( Kekspay_Data::get_settings( 'title' ) );
-
- $this->add_hooks();
- }
-
- /**
- * Register different hooks.
- */
- private function add_hooks() {
- add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
- add_action( 'woocommerce_receipt_' . $this->id, array( $this, 'do_receipt_page' ) );
- }
-
- /**
- * Check if we need to make gateways available.
- *
- * @override
- */
- public function is_available() {
- if ( ! Kekspay_Data::required_keys_set() || ! Kekspay_Data::currency_supported() ) {
- return false;
- }
-
- return parent::is_available();
- }
-
- /**
- * Add kekspay payment method icon.
- *
- * @override
- */
- public function get_icon() {
- return apply_filters( 'woocommerce_gateway_icon', Kekspay_Data::get_svg( 'keks-logo', [ 'class="kekspay-logo"' ] ), $this->id );
- }
-
- /**
- * Echoes gateway's options (Checkout tab under WooCommerce's settings).
- *
- * @override
- */
- public function admin_options() {
- ?>
-
-
-
- form_fields = include( KEKSPAY_DIR_PATH . '/includes/settings/kekspay-settings.php' );
- }
-
- /**
- * Display description of the gateway on the checkout page.
- *
- * @override
- */
- public function payment_fields() {
- echo '' . wptexturize( __( 'Najbrže i bez naknada putem KEKS Pay aplikacije!', 'kekspay' ) ) . '
';
-
- if ( Kekspay_Data::test_mode() ) {
- $test_mode_notice = apply_filters(
- 'kekspay_payment_description_test_mode_notice',
- '' . __( 'KEKS Pay je trenutno u testom načinu rada, ne zaboravite ga ugasiti po završetku testiranja.', 'kekspay' ) . '
'
- );
-
- if ( ! empty( $test_mode_notice ) ) {
- echo $test_mode_notice;
- }
- }
- }
-
- /**
- * Trigger actions for 'receipt' page.
- *
- * @param int $order_id
- */
- public function do_receipt_page( $order_id ) {
- $order = wc_get_order( $order_id );
-
- if ( ! $order ) {
- Kekspay_Logger::log( 'Failed to find order ' . $order_id . ' while trying to show receipt page.', 'warning' );
- return false;
- }
-
- if ( ! $order->get_meta( 'kekspay_status' ) ) {
- Kekspay_Logger::log( 'Order ' . $order_id . ' created for payment via KEKS Pay, status set to pending.', 'info' );
- $order->add_meta_data( 'kekspay_status', 'pending', true );
- $order->save();
- }
-
- // Add order meta and note to mark order as TEST if test mode is enabled or order already has not been maked as TEST.
- if ( Kekspay_Data::test_mode() && ! Kekspay_Data::order_test_mode( $order ) ) {
- $order->add_order_note( __( 'Narudžba napravljena u testnom načinu rada!', 'kekspay' ) );
- $order->add_meta_data( 'kekspay_test_mode', 'yes', true );
- $order->save();
- }
-
- do_action( 'kekspay_receipt_before_payment_data', $order, Kekspay_Data::get_settings() );
-
- ?>
-
-
-
-
-
- sell->display_sell_url( $order ); ?>
-
-
-
-
- sell->display_sell_qr( $order ); ?>
-
-
-
-
- cart->empty_cart();
-
- return array(
- 'result' => 'success',
- 'redirect' => $order->get_checkout_payment_url( true ),
- );
- }
-
- /**
- * Process refund via KEKS Pay.
- *
- * @override
- * @param int $order_id
- * @param float $amount Defaults to null.
- * @param string $reason Defaults to empty string.
- *
- * @return bool True or false based on success, or a WP_Error object.
- */
- public function process_refund( $order_id, $amount = null, $reason = '' ) {
- $order = wc_get_order( $order_id );
- if ( ! $order ) {
- Kekspay_Logger::log( 'Failed to find order ' . $order_id . ' while processing refund.', 'warning' );
- return false;
- }
-
- return $this->connector->refund( $order, $amount );
- }
-
- }
+ /**
+ * Kekspay_Payment_Gateway class
+ */
+ class Kekspay_Payment_Gateway extends WC_Payment_Gateway {
+
+ /**
+ * App data handler.
+ *
+ * @var Kekspay_Sell
+ */
+ private $sell;
+
+ /**
+ * Class constructor with basic gateway's setup.
+ */
+ public function __construct() {
+ require_once KEKSPAY_DIR_PATH . '/includes/core/class-kekspay-connector.php';
+ require_once KEKSPAY_DIR_PATH . '/includes/core/class-kekspay-sell.php';
+
+ $this->id = KEKSPAY_PLUGIN_ID;
+ $this->method_title = __( 'KEKS Pay', 'kekspay' );
+ $this->method_description = __( 'Najbrže i bez naknada putem KEKS Pay aplikacije!', 'kekspay' );
+ $this->has_fields = true;
+
+ $this->init_form_fields();
+ $this->init_settings();
+
+ $this->supports = [ 'products', 'refunds' ];
+
+ $this->sell = new Kekspay_Sell();
+
+ $this->title = esc_attr( Kekspay_Data::get_settings( 'title' ) );
+
+ $this->add_hooks();
+ }
+
+ /**
+ * Register different hooks.
+ */
+ private function add_hooks() {
+ add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, [ $this, 'process_admin_options' ] );
+ add_action( 'woocommerce_receipt_' . $this->id, [ $this, 'do_receipt_page' ] );
+ }
+
+ /**
+ * Check if we need to make gateways available.
+ *
+ * @override
+ */
+ public function is_available() {
+ if ( ! Kekspay_Data::required_keys_set() || ! Kekspay_Data::currency_supported() ) {
+ return false;
+ }
+
+ return parent::is_available();
+ }
+
+ /**
+ * Add kekspay payment method icon.
+ *
+ * @override
+ */
+ public function get_icon() {
+ return apply_filters( 'woocommerce_gateway_icon', Kekspay_Data::get_svg( 'keks-logo', [ 'class="kekspay-logo"' ] ), $this->id );
+ }
+
+ /**
+ * Echoes gateway's options (Checkout tab under WooCommerce's settings).
+ *
+ * @override
+ */
+ public function admin_options() {
+ ?>
+
+
+
+ form_fields = include KEKSPAY_DIR_PATH . '/includes/settings/kekspay-settings.php';
+ }
+
+ /**
+ * Display description of the gateway on the checkout page.
+ *
+ * @override
+ */
+ public function payment_fields() {
+ echo wp_kses_post( '' . __( 'Najbrže i bez naknada putem KEKS Pay aplikacije!', 'kekspay' ) . '
' );
+
+ if ( Kekspay_Data::test_mode() ) {
+ echo wp_kses_post(
+ apply_filters(
+ 'kekspay_payment_description_test_mode_notice',
+ '' . __( 'KEKS Pay je trenutno u testom načinu rada, ne zaboravite ga ugasiti po završetku testiranja.', 'kekspay' ) . '
'
+ )
+ );
+ }
+ }
+
+ /**
+ * Trigger actions for 'receipt' page.
+ *
+ * @param int $order_id
+ */
+ public function do_receipt_page( $order_id ) {
+ $order = wc_get_order( $order_id );
+
+ if ( ! $order ) {
+ Kekspay_Logger::log( 'Failed to find order ' . $order_id . ' while trying to show receipt page.', 'warning' );
+ return false;
+ }
+
+ if ( ! $order->get_meta( 'kekspay_status' ) ) {
+ Kekspay_Logger::log( 'Order ' . $order_id . ' created for payment via KEKS Pay, status set to pending.', 'info' );
+ $order->add_meta_data( 'kekspay_status', 'pending', true );
+ $order->save();
+ }
+
+ // Add order meta and note to mark order as TEST if test mode is enabled or order already has not been maked as TEST.
+ if ( Kekspay_Data::test_mode() && ! Kekspay_Data::order_test_mode( $order ) ) {
+ $order->add_order_note( __( 'Narudžba napravljena u testnom načinu rada!', 'kekspay' ) );
+ $order->add_meta_data( 'kekspay_test_mode', 'yes', true );
+ $order->save();
+ }
+
+ do_action( 'kekspay_receipt_before_payment_data', $order, Kekspay_Data::get_settings() );
+ ?>
+
+
+
+
+
+
+ sell->display_sell_url( $order ) ); ?>
+
+
+
+
+ sell->display_sell_qr( $order ); //@codingStandardsIgnoreLine - safe output ?>
+
+
+
+ cart->empty_cart();
+
+ return [
+ 'result' => 'success',
+ 'redirect' => $order->get_checkout_payment_url( true ),
+ ];
+ }
+
+ /**
+ * Process refund via KEKS Pay.
+ *
+ * @override
+ * @param int $order_id
+ * @param float $amount Defaults to null.
+ * @param string $reason Defaults to empty string.
+ *
+ * @return bool True or false based on success, or a WP_Error object.
+ */
+ public function process_refund( $order_id, $amount = null, $reason = '' ) {
+ $order = wc_get_order( $order_id );
+ if ( ! $order ) {
+ Kekspay_Logger::log( 'Failed to find order ' . $order_id . ' while processing refund.', 'warning' );
+ return false;
+ }
+
+ return Kekspay_Connector::refund( $order, $amount );
+ }
+
+ }
}
diff --git a/includes/core/class-kekspay-sell.php b/includes/core/class-kekspay-sell.php
index 20dda83..505f3fd 100644
--- a/includes/core/class-kekspay-sell.php
+++ b/includes/core/class-kekspay-sell.php
@@ -1,114 +1,115 @@
6,
- 'quietzoneSize' => 4,
- 'eccLevel' => QRCode::ECC_L,
- 'imageTransparent' => false,
- )
- );
-
- $qrcode = new QRCode( $options );
-
- return $qrcode->render( wp_json_encode( $data ) );
- } catch ( \Exception $e ) {
- Kekspay_Logger::log( 'Failed to create QR Code. Exception message: ' . $e->getMessage(), 'error' );
- }
-
- return false;
- }
-
- /**
- * Format QR Code with html for display.
- *
- * @param object $order Order for which to fetch QR code.
- *
- * @return string Path to or base64 encoded QR code for mobile app wrapped in img tags.
- */
- public function display_sell_qr( $order ) {
- $qrcode = $this->get_sell_qr( $order );
-
- if ( ! $qrcode ) {
- return esc_html_e( 'Dogodila se greška prilikom kreiranja QR kȏda za ovu narudžbu. Molimo rekreirajte narudžbu ili kontaktirajte vlasnika web stranice.', 'kekspay' );
- }
-
- return apply_filters( 'kekspay_sell_qr_code', '
', $qrcode );
- }
-
- /**
- * Format Keks pay url with html for display
- *
- * @param object $order Order for which to get the pay url.
- *
- * @return string Link for payment.
- */
- public function display_sell_url( $order ) {
- $sell_url = $this->get_sell_url( $order );
-
- if ( ! $sell_url ) {
- return esc_html_e( 'Dogodila se greška prilikom kreiranja poveznice za plaćanje putem KEKS Pay mobilne aplikacije za ovu narudžbu. Molimo rekreirajte narudžbu ili kontaktirajte vlasnika web stranice."', 'kekspay' );
- }
-
- $attrs = apply_filters(
- 'kekspay_sell_link_attributes',
- array(
- 'id' => 'kekspay-pay-url',
- 'class' => 'button kekspay-sell-button',
- 'target' => '_blank',
- 'label' => __( 'Otvori KEKS Pay', 'kekspay' ),
- )
- );
-
- return apply_filters( 'kekspay_sell_link', '' . esc_html( $attrs['label'] ) . ' ' );
- }
-
- }
+ /**
+ * Kekspay_Sell class
+ *
+ * @since 0.1
+ */
+ class Kekspay_Sell {
+
+ /**
+ * Class constructor.
+ */
+ public function __construct() {
+ require_once KEKSPAY_DIR_PATH . 'vendor/autoload.php';
+ }
+
+ /**
+ * Create url for mobile app.
+ *
+ * @param object $order Order for which to create url.
+ *
+ * @return string Url for mobile app.
+ */
+ public function get_sell_url( $order ) {
+ $sell = Kekspay_Data::get_sell_data( $order, true );
+
+ if ( ! $sell ) {
+ return false;
+ }
+
+ return add_query_arg( $sell, Kekspay_Data::get_kekspay_pay_base() );
+ }
+
+ /**
+ * Create QR code for mobile app.
+ *
+ * @param object $order Order for which to create QR code.
+ *
+ * @return string base64 encoded png file.
+ */
+ public function get_sell_qr( $order ) {
+ $data = Kekspay_Data::get_sell_data( $order );
+
+ try {
+ $options = new QROptions(
+ [
+ 'version' => 6,
+ 'quietzoneSize' => 4,
+ 'eccLevel' => QRCode::ECC_L,
+ 'imageTransparent' => false,
+ ]
+ );
+
+ $qrcode = new QRCode( $options );
+
+ return $qrcode->render( wp_json_encode( $data ) );
+ } catch ( \Exception $e ) {
+ Kekspay_Logger::log( 'Failed to create QR Code. Exception message: ' . $e->getMessage(), 'error' );
+ }
+
+ return false;
+ }
+
+ /**
+ * Format QR Code with html for display.
+ *
+ * @param object $order Order for which to fetch QR code.
+ *
+ * @return string Path to or base64 encoded QR code for mobile app wrapped in img tags.
+ */
+ public function display_sell_qr( $order ) {
+ $qrcode = $this->get_sell_qr( $order );
+
+ if ( ! $qrcode ) {
+ return esc_html_e( 'Dogodila se greška prilikom kreiranja QR kȏda za ovu narudžbu. Molimo rekreirajte narudžbu ili kontaktirajte vlasnika web stranice.', 'kekspay' );
+ }
+
+ return apply_filters( 'kekspay_sell_qr_code', '
', $qrcode );
+ }
+
+ /**
+ * Format Keks pay url with html for display
+ *
+ * @param object $order Order for which to get the pay url.
+ *
+ * @return string Link for payment.
+ */
+ public function display_sell_url( $order ) {
+ $sell_url = $this->get_sell_url( $order );
+
+ if ( ! $sell_url ) {
+ return esc_html_e( 'Dogodila se greška prilikom kreiranja poveznice za plaćanje putem KEKS Pay mobilne aplikacije za ovu narudžbu. Molimo rekreirajte narudžbu ili kontaktirajte vlasnika web stranice."', 'kekspay' );
+ }
+
+ $attrs = apply_filters(
+ 'kekspay_sell_link_attributes',
+ [
+ 'id' => 'kekspay-pay-url',
+ 'class' => 'button kekspay-sell-button',
+ 'target' => '_blank',
+ 'label' => __( 'Otvori KEKS Pay', 'kekspay' ),
+ ]
+ );
+
+ return apply_filters( 'kekspay_sell_link', '' . esc_html( $attrs['label'] ) . ' ' );
+ }
+
+ }
}
diff --git a/includes/settings/kekspay-settings.php b/includes/settings/kekspay-settings.php
index 0dbdb53..73fb1bd 100644
--- a/includes/settings/kekspay-settings.php
+++ b/includes/settings/kekspay-settings.php
@@ -1,104 +1,106 @@
array(
- 'title' => __( 'Omogući KEKS Pay', 'kekspay' ),
- 'type' => 'checkbox',
- 'label' => __( 'Omogući KEKS Pay metodu plaćanja.', 'kekspay' ),
- 'default' => 'no',
- 'desc_tip' => false,
- ),
- 'title' => array(
- 'title' => __( 'Naslov', 'kekspay' ),
- 'type' => 'text',
- 'description' => __( 'Naslov KEKS Pay metode plaćanja koji korisnik vidi na stranici za naplatu. Upišite: KEKS Pay.', 'kekspay' ),
- 'default' => _x( 'KEKS Pay', 'Title default value', 'kekspay' ),
- 'desc_tip' => true,
- ),
- 'auth-token' => array(
- 'title' => __( 'Sigurnosni token', 'kekspay' ),
- 'type' => 'title',
- 'description' => Kekspay_Data::get_settings_token_field(),
- ),
- 'webshop-options' => array(
- 'title' => __( 'Podaci o Web trgovini', 'kekspay' ),
- 'type' => 'title',
- 'description' => '',
- ),
- 'webshop-cid' => array(
- 'title' => __( 'CID', 'kekspay' ),
- 'type' => 'text',
- 'description' => __( 'Jedinstveni identifikator Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
- 'default' => '',
- 'desc_tip' => true,
- 'required' => true,
- ),
- 'webshop-tid' => array(
- 'title' => __( 'TID', 'kekspay' ),
- 'type' => 'text',
- 'description' => __( 'Jedinstven identifikator za vrstu usluge unutar Web trgovine. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
- 'default' => '',
- 'desc_tip' => true,
- ),
- 'webshop-secret-key' => array(
- 'title' => __( 'Tajni ključ', 'kekspay' ),
- 'type' => 'password',
- 'description' => __( 'Tajni ključ Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
- 'default' => '',
- 'desc_tip' => true,
- ),
- 'test-webshop-cid' => array(
- 'title' => __( 'TEST CID', 'kekspay' ),
- 'type' => 'text',
- 'description' => __( 'Jedinstven testni identifikator Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
- 'default' => '',
- 'desc_tip' => true,
- ),
- 'test-webshop-tid' => array(
- 'title' => __( 'TEST TID', 'kekspay' ),
- 'type' => 'text',
- 'description' => __( 'Jedinstven testni identifikator Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
- 'default' => '',
- 'desc_tip' => true,
- ),
- 'test-webshop-secret-key' => array(
- 'title' => __( 'TEST Tajni ključ', 'kekspay' ),
- 'type' => 'password',
- 'description' => __( 'Testni tajni ključ Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
- 'default' => '',
- 'desc_tip' => true,
- ),
- 'advanced-options' => array(
- 'title' => __( 'Dodatne postavke', 'kekspay' ),
- 'type' => 'title',
- 'description' => '',
- ),
- 'payed-order-status' => array(
- 'title' => __( 'Status plaćene narudžbe', 'kekspay' ),
- 'type' => 'select',
- 'description' => sprintf( __( 'Status narudžbe koji će biti postavljen nakon što KEKS Pay uspješno izvrši naplatu same narudžbe. (Zadani status je "%s").', 'kekspay' ), _x( 'Processing', 'Order status', 'woocommerce' ) ),
- 'default' => 'wc-processing',
- 'options' => wc_get_order_statuses(),
- ),
- 'in-test-mode' => array(
- 'title' => __( 'Testni način rada', 'kekspay' ),
- 'type' => 'checkbox',
- 'label' => __( 'Uključi testni način rada.', 'kekspay' ),
- 'description' => __( 'Način rada koji omogućava testiranje, ne zaboravite ga ugasiti po završetku testiranja.', 'kekspay' ),
- 'default' => 'no',
- 'desc_tip' => true,
- ),
- 'use-logger' => array(
- 'title' => __( 'Zapisnik grešaka', 'kekspay' ),
- 'type' => 'checkbox',
- 'label' => __( 'Uključi zapisnik grešaka', 'kekspay' ),
- 'description' => sprintf( __( 'Zapisuje procese i greške pri radu, zapisnik je pohranjen u: %s. Zapisnik može sadržavati osjetljive informacije. Preporučamo korištenje zapisnika samo u svrhe otkrivanja te otklanjanja grešaka te brisanje zapisnika po završetku.', 'kekspay' ), '' . WC_Log_Handler_File::get_log_file_path( 'kekspay' ) . '
' ),
- 'default' => 'no',
- ),
- )
+ 'wc_kekspay_settings',
+ [
+ 'enabled' => [
+ 'title' => __( 'Omogući KEKS Pay', 'kekspay' ),
+ 'type' => 'checkbox',
+ 'label' => __( 'Omogući KEKS Pay metodu plaćanja.', 'kekspay' ),
+ 'default' => 'no',
+ 'desc_tip' => false,
+ ],
+ 'title' => [
+ 'title' => __( 'Naslov', 'kekspay' ),
+ 'type' => 'text',
+ 'description' => __( 'Naslov KEKS Pay metode plaćanja koji korisnik vidi na stranici za naplatu. Upišite: KEKS Pay.', 'kekspay' ),
+ 'default' => _x( 'KEKS Pay', 'Title default value', 'kekspay' ),
+ 'desc_tip' => true,
+ ],
+ 'auth-token' => [
+ 'title' => __( 'Sigurnosni token', 'kekspay' ),
+ 'type' => 'title',
+ 'description' => Kekspay_Data::get_settings_token_field(),
+ ],
+ 'webshop-options' => [
+ 'title' => __( 'Podaci o Web trgovini', 'kekspay' ),
+ 'type' => 'title',
+ 'description' => '',
+ ],
+ 'webshop-cid' => [
+ 'title' => __( 'CID', 'kekspay' ),
+ 'type' => 'text',
+ 'description' => __( 'Jedinstveni identifikator Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
+ 'default' => '',
+ 'desc_tip' => true,
+ 'required' => true,
+ ],
+ 'webshop-tid' => [
+ 'title' => __( 'TID', 'kekspay' ),
+ 'type' => 'text',
+ 'description' => __( 'Jedinstven identifikator za vrstu usluge unutar Web trgovine. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
+ 'default' => '',
+ 'desc_tip' => true,
+ ],
+ 'webshop-secret-key' => [
+ 'title' => __( 'Tajni ključ', 'kekspay' ),
+ 'type' => 'password',
+ 'description' => __( 'Tajni ključ Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
+ 'default' => '',
+ 'desc_tip' => true,
+ ],
+ 'test-webshop-cid' => [
+ 'title' => __( 'TEST CID', 'kekspay' ),
+ 'type' => 'text',
+ 'description' => __( 'Jedinstven testni identifikator Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
+ 'default' => '',
+ 'desc_tip' => true,
+ ],
+ 'test-webshop-tid' => [
+ 'title' => __( 'TEST TID', 'kekspay' ),
+ 'type' => 'text',
+ 'description' => __( 'Jedinstven testni identifikator Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
+ 'default' => '',
+ 'desc_tip' => true,
+ ],
+ 'test-webshop-secret-key' => [
+ 'title' => __( 'TEST Tajni ključ', 'kekspay' ),
+ 'type' => 'password',
+ 'description' => __( 'Testni tajni ključ Web trgovine unutar KEKS Pay sustava. Bit će dodijeljen od strane KEKS Pay sustava.', 'kekspay' ),
+ 'default' => '',
+ 'desc_tip' => true,
+ ],
+ 'advanced-options' => [
+ 'title' => __( 'Dodatne postavke', 'kekspay' ),
+ 'type' => 'title',
+ 'description' => '',
+ ],
+ 'payed-order-status' => [
+ 'title' => __( 'Status plaćene narudžbe', 'kekspay' ),
+ 'type' => 'select',
+ /* translators: order status for payment complete */
+ 'description' => sprintf( __( 'Status narudžbe koji će biti postavljen nakon što KEKS Pay uspješno izvrši naplatu same narudžbe. (Zadani status je "%s").', 'kekspay' ), _x( 'Processing', 'Order status', 'woocommerce' ) ),
+ 'default' => 'wc-processing',
+ 'options' => wc_get_order_statuses(),
+ ],
+ 'in-test-mode' => [
+ 'title' => __( 'Testni način rada', 'kekspay' ),
+ 'type' => 'checkbox',
+ 'label' => __( 'Uključi testni način rada.', 'kekspay' ),
+ 'description' => __( 'Način rada koji omogućava testiranje, ne zaboravite ga ugasiti po završetku testiranja.', 'kekspay' ),
+ 'default' => 'no',
+ 'desc_tip' => true,
+ ],
+ 'use-logger' => [
+ 'title' => __( 'Zapisnik grešaka', 'kekspay' ),
+ 'type' => 'checkbox',
+ 'label' => __( 'Uključi zapisnik grešaka', 'kekspay' ),
+ /* translators: issue logger. */
+ 'description' => sprintf( __( 'Zapisuje procese i greške pri radu, zapisnik je pohranjen u: %s. Zapisnik može sadržavati osjetljive informacije. Preporučamo korištenje zapisnika samo u svrhe otkrivanja te otklanjanja grešaka te brisanje zapisnika po završetku.', 'kekspay' ), '' . WC_Log_Handler_File::get_log_file_path( 'kekspay' ) . '
' ),
+ 'default' => 'no',
+ ],
+ ]
);
diff --git a/includes/utilities/class-kekspay-data.php b/includes/utilities/class-kekspay-data.php
index c128872..e23d939 100644
--- a/includes/utilities/class-kekspay-data.php
+++ b/includes/utilities/class-kekspay-data.php
@@ -1,364 +1,367 @@
get_meta( 'kekspay_test_mode' );
- }
-
- /**
- * Returns true if required keys in gateways settings are set, false otherwise.
- *
- * @return bool
- */
- public static function required_keys_set() {
- if ( ! self::get_settings( 'webshop-cid', true ) || ! self::get_settings( 'webshop-tid', true ) || ! self::get_settings( 'webshop-secret-key', true ) ) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns true if currency is EUR.
- *
- * @return bool
- */
- public static function currency_supported() {
- return 'EUR' === get_woocommerce_currency();
- }
-
- /**
- * Fetch settings for use.
- *
- * @param string $name Name of specific setting to fetch.
- * @param bool $test_check Whether to check if test mode is on to fetch test version of the setting.
- *
- * @return array/string
- */
- public static function get_settings( $name = false, $test_check = false ) {
- if ( empty( self::$settings ) ) {
- self::load_settings();
- }
-
- if ( $name ) {
- if ( $test_check ) {
- $name = self::test_mode() ? 'test-' . $name : $name;
- }
-
- return isset( self::$settings[ $name ] ) ? self::$settings[ $name ] : null;
- }
-
- return self::$settings;
- }
-
- /**
- * Return auth token or generate if there is none.
- *
- * @return string
- */
- public static function get_auth_token() {
- $token = self::get_settings( 'auth-token' );
- if ( ! $token ) {
- $token = hash_hmac( 'sha256', bin2hex( openssl_random_pseudo_bytes( 64 ) ), site_url() );
-
- self::set_settings( array( 'auth-token' => $token ) );
- }
-
- return $token;
- }
-
- /**
- * Return auth token or generate if there is none.
- *
- * @param bool $absolute Wheter to fetch full url with endpoint or only the endpoint.
- *
- * @return string
- */
- public static function get_svg( $svg ) {
- if ( ! $svg || ! file_exists( KEKSPAY_DIR_PATH . 'assets/dist/img/' . $svg . '.svg' ) ) {
- return false;
- }
-
- return file_get_contents( KEKSPAY_DIR_PATH . 'assets/dist/img/' . $svg . '.svg' );
- }
-
- /**
- * Return gateway endpoint on wc api.
- *
- * @param bool $absolute Wheter to fetch full url with endpoint or only the endpoint.
- *
- * @return string
- */
- public static function get_wc_endpoint( $absolute = false ) {
- return $absolute ? untrailingslashit( WC()->api_request_url( self::$endpoint ) ) : self::$endpoint;
- }
-
- /**
- * Return gateway url for KEKS Pay servers.
- *
- * @return string
- */
- public static function get_kekspay_pay_base( $trailingslash = false ) {
- $endpoint = self::$kekspay_pay . ( self::test_mode() ? 'galebpay' : 'pay' );
- return $trailingslash ? trailingslashit( $endpoint ) : $endpoint;
- }
-
- /**
- * Return gateway url for KEKS Pay servers.
- *
- * @return string
- */
- public static function get_kekspay_api_base() {
- return self::test_mode() ? self::$test_kekspay_api : self::$kekspay_api;
- }
-
- /**
- * Creates endpoint message for settings.
- *
- * @return string
- */
- public static function get_settings_token_field() {
- return sprintf(
- __( '%1$s Nakon pohrane unutar KEKS Pay sustava omogućava ovoj trgovini primanje obavijesti o stanju naplate. %2$s Kontakt %3$s', 'kekspay' ),
- '' . add_query_arg( 'token', self::get_auth_token(), self::get_wc_endpoint( true ) ) . '
',
- '',
- ' '
- );
- }
-
- /**
- * Creates unique bill id using webshop cid and order id.
- *
- * @return string
- */
- public static function get_bill_id_by_order_id( $order_id ) {
- $order = wc_get_order( $order_id );
- if ( ! $order ) {
- Kekspay_Logger::log( 'Could not fetch order with ID ' . $order_id . ' while generating bill_id.', 'error' );
- return false;
- }
- return self::get_settings( 'webshop-tid', true ) . '-' . $order_id;
- }
-
- /**
- * Extract order id from kekspay bill id.
- *
- * @return string
- */
- public static function get_order_id_by_bill_id( $bill_id ) {
- return str_replace( self::get_settings( 'webshop-tid', true ) . '-', '', $bill_id );
- }
-
- /**
- * Extract order id from kekspay bill id.
- *
- * @return string
- */
- public static function get_algo() {
- return self::$algo;
- }
-
- /**
- * Gathers all data needed for payment and formats it as array.
- *
- * @param object $order Order from which to extract data.
- * @param bool $callbacks Whether to include callback urls or not.
- *
- * @return array/bool Extracted data as array, false on failure.
- */
- public static function get_sell_data( $order, $callbacks = false ) {
- if ( ! self::required_keys_set() ) {
- Kekspay_Logger::log( 'Payment gateway setup incomplete, please enter all requested data to gateway settings.', 'error' );
- return false;
- }
-
- $sell = array(
- 'qr_type' => 1,
- 'cid' => self::get_settings( 'webshop-cid', true ),
- 'tid' => self::get_settings( 'webshop-tid', true ),
- 'bill_id' => self::get_bill_id_by_order_id( $order->get_id() ),
- 'amount' => $order->get_total(),
- 'currency' => $order->get_currency(),
- );
-
- if ( $callbacks ) {
- $sell['success_url'] = $order->get_checkout_order_received_url();
- $sell['fail_url'] = $order->get_cancel_order_url_raw();
- }
-
- return $sell;
- }
-
- /**
- * Detects the cipher to use based on the key stored.
- * Currently supporting: - 3DES
- * - AES
- *
- * @param string $key Secret key used for hashing.
- *
- * @return string
- */
- public static function get_cipher( $key ) {
- $key_size = strlen( $key );
-
- if ( ctype_xdigit( $key ) ) {
- if ( $key_size === 24 ) {
- self::$algo = 0;
- return 'des-ede3-cbc';
- } else {
- throw new Exception( 'Secret key must be 24 bytes.' );
- }
- } else {
- if ( in_array( $key_size, array( 16, 24, 32 ), true ) ) {
- self::$algo = 1;
- return 'aes-' . ( $key_size * 8 ) . '-cbc';
- } else {
- throw new Exception( 'Secret key must be 16, 24 or 32 bytes.' );
- }
- }
- }
-
- /**
- * Return hash created from the provided data and secret.
- *
- * @param object $order Order from which to extract data for hash.
- * @param string $timestamp Timestamp for creating hash.
- *
- * @return string
- */
- public static function get_hash( $order, $amount, $timestamp ) {
- try {
- // Get hashing key from the plugins settings.
- $key = self::get_settings( 'webshop-secret-key', true );
- // Define the cipher used for hashing.
- $cipher = self::get_cipher( $key );
- // Concat epochtime + webshop tid + order amount + bill_id for payload.
- $payload = $timestamp . self::get_settings( 'webshop-tid', true ) . $amount . self::get_bill_id_by_order_id( $order->get_id() );
- // Extract bytes from md5 hex hash.
- $payload_checksum = pack( 'H*', md5( $payload ) );
- // Create 8 or 16 (depending on cipher) byte binary initialization vector.
- $iv = str_repeat( pack( 'c', 0 ), false !== strpos( $cipher, 'aes' ) ? 16 : 8 );
- // Encrypt data using 3DES or AES cipher and convert it to hex.
- $hash = bin2hex( openssl_encrypt( $payload_checksum, $cipher, $key, OPENSSL_RAW_DATA, $iv ) );
-
- return strtoupper( $hash );
- } catch ( Exception $e ) {
- Kekspay_Logger::log( 'Error while generating hash:' . $e->getMessage(), 'error' );
- }
-
- }
-
- }
+ /**
+ * Kekspay_Data class
+ *
+ * @since 0.1
+ */
+ class Kekspay_Data {
+ /**
+ * Whether or not logging is enabled.
+ *
+ * @var array
+ */
+ private static $settings = [];
+
+ /**
+ * Set endpoint for webshop api.
+ *
+ * @var string
+ */
+ private static $endpoint = 'wc-kekspay';
+
+ /**
+ * Set base url of kekspay pay.
+ *
+ * @var string
+ */
+ private static $kekspay_pay = 'https://kekspay.hr/';
+
+ /**
+ * Set base url of kekspay API.
+ *
+ * @var string
+ */
+ private static $kekspay_api = 'https://ewa.erstebank.hr/eretailer/';
+
+ /**
+ * Set base test url of kekspay API.
+ *
+ * @var string
+ */
+ private static $test_kekspay_api = 'https://kekspayuat.erstebank.hr/eretailer/';
+
+ /**
+ * Per Kekpay documentation, parametar "algo" needs to be sent with the requests that use hash.
+ * Value of "algo" tells Kekspay servers which cipher was used for hashing:
+ * 0 : 3DES
+ * 1 : AES
+ *
+ * @var string
+ */
+ private static $algo;
+
+ /**
+ * Init data class.
+ */
+ public function __construct() {
+ self::load_settings();
+ }
+
+ /**
+ * Load gateway settings from the database.
+ *
+ * @return void
+ */
+ public static function load_settings() {
+ self::$settings = get_option( 'woocommerce_' . KEKSPAY_PLUGIN_ID . '_settings', [] );
+ }
+
+ /**
+ * Save gateway settings to the database.
+ *
+ * @return void
+ */
+ public static function set_settings( $settings ) {
+ update_option( 'woocommerce_' . KEKSPAY_PLUGIN_ID . '_settings', array_merge( self::get_settings(), $settings ) );
+ }
+
+ /**
+ * Returns if payment gateway is enabled.
+ *
+ * @return bool
+ */
+ public static function enabled() {
+ if ( empty( self::$settings ) ) {
+ self::load_settings();
+ }
+
+ return isset( self::$settings['enabled'] ) && 'yes' === self::$settings['enabled'];
+ }
+
+ /**
+ * Returns true if test mode is turned on, false otherwise.
+ *
+ * @return bool
+ */
+ public static function test_mode() {
+ if ( empty( self::$settings ) ) {
+ self::load_settings();
+ }
+
+ return 'yes' === self::$settings['in-test-mode'];
+ }
+
+ /**
+ * Returns true if order was created in test mode, false otherwise.
+ *
+ * @return bool
+ */
+ public static function order_test_mode( $order ) {
+ return 'yes' === $order->get_meta( 'kekspay_test_mode' );
+ }
+
+ /**
+ * Returns true if required keys in gateways settings are set, false otherwise.
+ *
+ * @return bool
+ */
+ public static function required_keys_set() {
+ if ( ! self::get_settings( 'webshop-cid', true ) || ! self::get_settings( 'webshop-tid', true ) || ! self::get_settings( 'webshop-secret-key', true ) ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if currency is EUR.
+ *
+ * @return bool
+ */
+ public static function currency_supported() {
+ return 'EUR' === get_woocommerce_currency();
+ }
+
+ /**
+ * Fetch settings for use.
+ *
+ * @param string $name Name of specific setting to fetch.
+ * @param bool $test_check Whether to check if test mode is on to fetch test version of the setting.
+ *
+ * @return array/string
+ */
+ public static function get_settings( $name = false, $test_check = false ) {
+ if ( empty( self::$settings ) ) {
+ self::load_settings();
+ }
+
+ if ( $name ) {
+ if ( $test_check ) {
+ $name = self::test_mode() ? 'test-' . $name : $name;
+ }
+
+ return isset( self::$settings[ $name ] ) ? self::$settings[ $name ] : null;
+ }
+
+ return self::$settings;
+ }
+
+ /**
+ * Return auth token or generate if there is none.
+ *
+ * @return string
+ */
+ public static function get_auth_token() {
+ $token = self::get_settings( 'auth-token' );
+ if ( ! $token ) {
+ $token = hash_hmac( 'sha256', bin2hex( openssl_random_pseudo_bytes( 64 ) ), site_url() );
+
+ self::set_settings( [ 'auth-token' => $token ] );
+ }
+
+ return $token;
+ }
+
+ /**
+ * Return auth token or generate if there is none.
+ *
+ * @param bool $absolute Wheter to fetch full url with endpoint or only the endpoint.
+ *
+ * @return string
+ */
+ public static function get_svg( $svg ) {
+ if ( ! $svg || ! file_exists( KEKSPAY_DIR_PATH . 'assets/dist/img/' . $svg . '.svg' ) ) {
+ return false;
+ }
+
+ return file_get_contents( KEKSPAY_DIR_PATH . 'assets/dist/img/' . $svg . '.svg' ); // @codingStandardsIgnoreLine - safe use of file_get_contents
+ }
+
+ /**
+ * Return gateway endpoint on wc api.
+ *
+ * @param bool $absolute Wheter to fetch full url with endpoint or only the endpoint.
+ *
+ * @return string
+ */
+ public static function get_wc_endpoint( $absolute = false ) {
+ return $absolute ? untrailingslashit( WC()->api_request_url( self::$endpoint ) ) : self::$endpoint;
+ }
+
+ /**
+ * Return gateway url for KEKS Pay servers.
+ *
+ * @return string
+ */
+ public static function get_kekspay_pay_base( $trailingslash = false ) {
+ $endpoint = self::$kekspay_pay . ( self::test_mode() ? 'galebpay' : 'pay' );
+ return $trailingslash ? trailingslashit( $endpoint ) : $endpoint;
+ }
+
+ /**
+ * Return gateway url for KEKS Pay servers.
+ *
+ * @return string
+ */
+ public static function get_kekspay_api_base() {
+ return self::test_mode() ? self::$test_kekspay_api : self::$kekspay_api;
+ }
+
+ /**
+ * Creates endpoint message for settings.
+ *
+ * @return string
+ */
+ public static function get_settings_token_field() {
+ return sprintf(
+ /* translators: token info. */
+ __( '%1$s Nakon pohrane unutar KEKS Pay sustava omogućava ovoj trgovini primanje obavijesti o stanju naplate. %2$s Kontakt %3$s', 'kekspay' ),
+ '' . add_query_arg( 'token', self::get_auth_token(), self::get_wc_endpoint( true ) ) . '
',
+ '',
+ ' '
+ );
+ }
+
+ /**
+ * Creates unique bill id using webshop cid and order id.
+ *
+ * @return string
+ */
+ public static function get_bill_id_by_order_id( $order_id ) {
+ $order = wc_get_order( $order_id );
+ if ( ! $order ) {
+ Kekspay_Logger::log( 'Could not fetch order with ID ' . $order_id . ' while generating bill_id.', 'error' );
+ return false;
+ }
+ return self::get_settings( 'webshop-tid', true ) . '-' . $order_id;
+ }
+
+ /**
+ * Extract order id from kekspay bill id.
+ *
+ * @return string
+ */
+ public static function get_order_id_by_bill_id( $bill_id ) {
+ return str_replace( self::get_settings( 'webshop-tid', true ) . '-', '', $bill_id );
+ }
+
+ /**
+ * Extract order id from kekspay bill id.
+ *
+ * @return string
+ */
+ public static function get_algo() {
+ return self::$algo;
+ }
+
+ /**
+ * Gathers all data needed for payment and formats it as array.
+ *
+ * @param object $order Order from which to extract data.
+ * @param bool $callbacks Whether to include callback urls or not.
+ *
+ * @return array/bool Extracted data as array, false on failure.
+ */
+ public static function get_sell_data( $order, $callbacks = false ) {
+ if ( ! self::required_keys_set() ) {
+ Kekspay_Logger::log( 'Payment gateway setup incomplete, please enter all requested data to gateway settings.', 'error' );
+ return false;
+ }
+
+ $sell = [
+ 'qr_type' => 1,
+ 'cid' => self::get_settings( 'webshop-cid', true ),
+ 'tid' => self::get_settings( 'webshop-tid', true ),
+ 'bill_id' => self::get_bill_id_by_order_id( $order->get_id() ),
+ 'amount' => $order->get_total(),
+ 'currency' => $order->get_currency(),
+ ];
+
+ if ( $callbacks ) {
+ $sell['success_url'] = $order->get_checkout_order_received_url();
+ $sell['fail_url'] = $order->get_cancel_order_url_raw();
+ }
+
+ return $sell;
+ }
+
+ /**
+ * Detects the cipher to use based on the key stored.
+ * Currently supporting: - 3DES
+ * - AES
+ *
+ * @param string $key Secret key used for hashing.
+ *
+ * @throws Exception Issues with key length.
+ *
+ * @return string
+ */
+ public static function get_cipher( $key ) {
+ $key_size = strlen( $key );
+
+ if ( ctype_xdigit( $key ) ) {
+ if ( $key_size === 24 ) {
+ self::$algo = 0;
+ return 'des-ede3-cbc';
+ } else {
+ throw new Exception( 'Secret key must be 24 bytes.' );
+ }
+ } else {
+ if ( in_array( $key_size, [ 16, 24, 32 ], true ) ) {
+ self::$algo = 1;
+ return 'aes-' . ( $key_size * 8 ) . '-cbc';
+ } else {
+ throw new Exception( 'Secret key must be 16, 24 or 32 bytes.' );
+ }
+ }
+ }
+
+ /**
+ * Return hash created from the provided data and secret.
+ *
+ * @param object $order Order from which to extract data for hash.
+ * @param string $timestamp Timestamp for creating hash.
+ *
+ * @return string
+ */
+ public static function get_hash( $order, $amount, $timestamp ) {
+ try {
+ // Get hashing key from the plugins settings.
+ $key = (string) self::get_settings( 'webshop-secret-key', true );
+ // Define the cipher used for hashing.
+ $cipher = self::get_cipher( $key );
+ // Concat epochtime + webshop tid + order amount + bill_id for payload.
+ $payload = $timestamp . self::get_settings( 'webshop-tid', true ) . $amount . self::get_bill_id_by_order_id( $order->get_id() );
+ // Extract bytes from md5 hex hash.
+ $payload_checksum = pack( 'H*', md5( $payload ) );
+ // Create 8 or 16 (depending on cipher) byte binary initialization vector.
+ $iv = str_repeat( pack( 'c', 0 ), false !== strpos( $cipher, 'aes' ) ? 16 : 8 );
+ // Encrypt data using 3DES or AES cipher and convert it to hex.
+ $hash = bin2hex( openssl_encrypt( $payload_checksum, $cipher, $key, OPENSSL_RAW_DATA, $iv ) );
+
+ return strtoupper( $hash );
+ } catch ( Exception $e ) {
+ Kekspay_Logger::log( 'Error while generating hash:' . $e->getMessage(), 'error' );
+ }
+
+ }
+
+ }
}
diff --git a/includes/utilities/class-kekspay-logger.php b/includes/utilities/class-kekspay-logger.php
index 8de188c..87fa2dc 100644
--- a/includes/utilities/class-kekspay-logger.php
+++ b/includes/utilities/class-kekspay-logger.php
@@ -1,66 +1,66 @@
log(
- $level,
- 'Kekspay v' . KEKSPAY_PLUGIN_VERSION . ' - ' . $message,
- array(
- 'source' => KEKSPAY_PLUGIN_ID,
- )
- );
+ $logger->log(
+ $level,
+ 'Kekspay v' . KEKSPAY_PLUGIN_VERSION . ' - ' . $message,
+ [
+ 'source' => KEKSPAY_PLUGIN_ID,
+ ]
+ );
- return true;
- }
- }
+ return true;
+ }
+ }
}
diff --git a/package.json b/package.json
index 1b8ded1..08eb626 100644
--- a/package.json
+++ b/package.json
@@ -1,18 +1,18 @@
{
- "name": "KEKS Pay for WooCommerce",
- "version": "1.0.0",
- "description": "KEKS Pay build",
- "private": true,
- "devDependencies": {
- "copy-webpack-plugin": "^11.0.0",
- "image-minimizer-webpack-plugin": "^3.8.3",
- "imagemin-gifsicle": "^7.0.0",
- "imagemin-mozjpeg": "^10.0.0",
- "imagemin-optipng": "^8.0.0",
- "imagemin-svgo": "^10.0.1",
- "laravel-mix": "^6.0.49",
- "resolve-url-loader": "^5.0.0",
- "sass": "^1.72.0",
- "sass-loader": "^12.1.0"
- }
+ "name": "keks-pay-for-woocommerce",
+ "version": "1.0.0",
+ "description": "KEKS Pay assets build",
+ "private": true,
+ "devDependencies": {
+ "copy-webpack-plugin": "^11.0.0",
+ "image-minimizer-webpack-plugin": "^3.8.3",
+ "imagemin-gifsicle": "^7.0.0",
+ "imagemin-mozjpeg": "^10.0.0",
+ "imagemin-optipng": "^8.0.0",
+ "imagemin-svgo": "^10.0.1",
+ "laravel-mix": "^6.0.49",
+ "resolve-url-loader": "^5.0.0",
+ "sass": "^1.72.0",
+ "sass-loader": "^12.1.0"
+ }
}
diff --git a/phpcs.xml b/phpcs.xml
index 5743f54..000c6c3 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -1,109 +1,12 @@
-
-
- Neuralab coding standards for WP development
-
-
-
+
+
+
-
- /vendor/*
+
+ /assets/*
/node_modules/*
- */data/*
- */tests/*
- *.js
- *.css
+ /vendor/*
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- index.php
- singular.php
- single.php
- page.php
- 404.php
- template-*.php
- templates/*
- woocommerce/*
-
diff --git a/readme.txt b/readme.txt
index fc26db3..06ae7cf 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,10 +1,10 @@
=== KEKS Pay for WooCommerce ===
Contributors: erstebank
Tags: kekspay, woocommerce, gateway, payment
-Requires at least: 5.0
+Requires at least: 6.3
Tested up to: 6.5
-Requires PHP: 7.2
-Stable tag: 1.1.0
+Requires PHP: 7.4
+Stable tag: 2.0.0
License: GPL v3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html
@@ -32,9 +32,9 @@ On a side note, this plugin is provided “as-is” and we don't currently provi
= MINIMUM REQUIREMENTS =
-* WooCommerce 3.3 or greater.
-* WordPress 5.0 or greater.
-* PHP version 7.2 or greater.
+* WooCommerce 8.2 or greater.
+* WordPress 6.3 or greater.
+* PHP version 7.4 or greater.
* SSL must be installed on your site and active on your Checkout pages.
= INSTALL =
@@ -49,6 +49,9 @@ For more installation options check the [official WordPress documentation](https
== Changelog ==
+= 2.0.0 =
+* Drop PHP 7.2 support.
+
= 1.1.0 =
* Add assets build
* Add AES cipher support
diff --git a/vendor/chillerlan/php-qrcode/.github/FUNDING.yml b/vendor/chillerlan/php-qrcode/.github/FUNDING.yml
deleted file mode 100644
index fc89a67..0000000
--- a/vendor/chillerlan/php-qrcode/.github/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-ko_fi: codemasher
diff --git a/vendor/chillerlan/php-qrcode/.github/workflows/tests.yml b/vendor/chillerlan/php-qrcode/.github/workflows/tests.yml
deleted file mode 100644
index 5dd343a..0000000
--- a/vendor/chillerlan/php-qrcode/.github/workflows/tests.yml
+++ /dev/null
@@ -1,55 +0,0 @@
-# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
-# https://github.com/localheinz/php-library-template/blob/master/.github/workflows/continuous-integration.yml
-# https://github.com/sebastianbergmann/phpunit/blob/master/.github/workflows/ci.yml
-
-on:
- - pull_request
- - push
-
-name: "Continuous Integration"
-
-jobs:
-
- tests:
- name: "Unit Tests"
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- php-binary:
- - php7.2
- - php7.3
- - php7.4
-
- steps:
- - name: "Checkout"
- uses: actions/checkout@v1.1.0
-
- - name: "Install dependencies with composer"
- run: ${{ matrix.php-binary }} $(which composer) update --no-interaction --no-progress --no-suggest
-
- - name: "Run unit tests with phpunit"
- run: ${{ matrix.php-binary }} vendor/bin/phpunit --configuration=phpunit.xml --no-coverage
-
-
- code-coverage:
- name: "Code Coverage"
- runs-on: ubuntu-latest
-
- steps:
- - name: "Checkout"
- uses: actions/checkout@v1.1.0
-
- - name: "Install locked dependencies with composer"
- run: php7.4 $(which composer) install --no-interaction --no-progress --no-suggest
-
- - name: "Dump Xdebug filter with phpunit/phpunit"
- run: php7.4 vendor/bin/phpunit --configuration=phpunit.xml --dump-xdebug-filter=.build/phpunit/xdebug-filter.php
-
- - name: "Collect code coverage with Xdebug and phpunit/phpunit"
- run: php7.4 vendor/bin/phpunit --configuration=phpunit.xml --prepend=.build/phpunit/xdebug-filter.php
-
- - name: "Send code coverage report to Codecov.io"
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- run: bash <(curl -s https://codecov.io/bash)
diff --git a/vendor/chillerlan/php-qrcode/.gitignore b/vendor/chillerlan/php-qrcode/.gitignore
deleted file mode 100644
index ecebb99..0000000
--- a/vendor/chillerlan/php-qrcode/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-.build/*
-.idea/*
-vendor/*
-composer.lock
-*.phpunit.result.cache
diff --git a/vendor/chillerlan/php-qrcode/.idea/inspectionProfiles/Project_Default.xml b/vendor/chillerlan/php-qrcode/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..565a038
--- /dev/null
+++ b/vendor/chillerlan/php-qrcode/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/vendor/chillerlan/php-qrcode/.scrutinizer.yml b/vendor/chillerlan/php-qrcode/.scrutinizer.yml
deleted file mode 100644
index 7fdd2a4..0000000
--- a/vendor/chillerlan/php-qrcode/.scrutinizer.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-filter:
- excluded_paths:
- - examples/*
- - tests/*
- - vendor/*
diff --git a/vendor/chillerlan/php-qrcode/.travis.yml b/vendor/chillerlan/php-qrcode/.travis.yml
deleted file mode 100644
index 78b8d79..0000000
--- a/vendor/chillerlan/php-qrcode/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-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)
diff --git a/vendor/chillerlan/php-qrcode/README.md b/vendor/chillerlan/php-qrcode/README.md
index 075b2a3..3ad7bad 100644
--- a/vendor/chillerlan/php-qrcode/README.md
+++ b/vendor/chillerlan/php-qrcode/README.md
@@ -1,77 +1,84 @@
# chillerlan/php-qrcode
-A PHP7.2+ QR Code library based on the [implementation](https://github.com/kazuhikoarase/qrcode-generator) by [Kazuhiko Arase](https://github.com/kazuhikoarase),
+A PHP 7.4+ QR Code library based on the [implementation](https://github.com/kazuhikoarase/qrcode-generator) by [Kazuhiko Arase](https://github.com/kazuhikoarase),
namespaced, cleaned up, improved and other stuff.
+**Attention:** there is now also a javascript port: [chillerlan/js-qrcode](https://github.com/chillerlan/js-qrcode).
+
+[![PHP Version Support][php-badge]][php]
[![Packagist version][packagist-badge]][packagist]
-[![License][license-badge]][license]
-[![Travis CI][travis-badge]][travis]
+[![Continuous Integration][gh-action-badge]][gh-action]
[![CodeCov][coverage-badge]][coverage]
-[![Scrunitizer CI][scrutinizer-badge]][scrutinizer]
+[![Codacy][codacy-badge]][codacy]
[![Packagist downloads][downloads-badge]][downloads]
-[![PayPal donate][donate-badge]][donate]
-
-[![Continuous Integration][gh-action-badge]][gh-action]
-[packagist-badge]: https://img.shields.io/packagist/v/chillerlan/php-qrcode.svg?style=flat-square
+[php-badge]: https://img.shields.io/packagist/php-v/chillerlan/php-qrcode?logo=php&color=8892BF
+[php]: https://www.php.net/supported-versions.php
+[packagist-badge]: https://img.shields.io/packagist/v/chillerlan/php-qrcode.svg?logo=packagist
[packagist]: https://packagist.org/packages/chillerlan/php-qrcode
-[license-badge]: https://img.shields.io/github/license/chillerlan/php-qrcode.svg?style=flat-square
-[license]: https://github.com/chillerlan/php-qrcode/blob/main/LICENSE
-[travis-badge]: https://img.shields.io/travis/chillerlan/php-qrcode.svg?style=flat-square
-[travis]: https://travis-ci.org/chillerlan/php-qrcode
-[coverage-badge]: https://img.shields.io/codecov/c/github/chillerlan/php-qrcode.svg?style=flat-square
-[coverage]: https://codecov.io/github/chillerlan/php-qrcode
-[scrutinizer-badge]: https://img.shields.io/scrutinizer/g/chillerlan/php-qrcode.svg?style=flat-square
-[scrutinizer]: https://scrutinizer-ci.com/g/chillerlan/php-qrcode
-[downloads-badge]: https://img.shields.io/packagist/dt/chillerlan/php-qrcode.svg?style=flat-square
+[coverage-badge]: https://img.shields.io/codecov/c/github/chillerlan/php-qrcode/v4.3.x?logo=codecov
+[coverage]: https://app.codecov.io/gh/chillerlan/php-qrcode/tree/v4.3.x
+[codacy-badge]: https://img.shields.io/codacy/grade/edccfc4fe5a34b74b1c53ee03f097b8d/v4.3.x?logo=codacy
+[codacy]: https://app.codacy.com/gh/chillerlan/php-qrcode/dashboard?branch=v4.3.x
+[downloads-badge]: https://img.shields.io/packagist/dt/chillerlan/php-qrcode?logo=packagist
[downloads]: https://packagist.org/packages/chillerlan/php-qrcode/stats
-[donate-badge]: https://img.shields.io/badge/donate-paypal-ff33aa.svg?style=flat-square
-[donate]: https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4
-[gh-action-badge]: https://github.com/chillerlan/php-qrcode/workflows/Continuous%20Integration/badge.svg
-[gh-action]: https://github.com/chillerlan/php-qrcode/actions
+[gh-action-badge]: https://img.shields.io/github/actions/workflow/status/chillerlan/php-qrcode/tests.yml?branch=v4.3.x&logo=github
+[gh-action]: https://github.com/chillerlan/php-qrcode/actions/workflows/tests.yml?query=branch%3Av4.3.x
-## Documentation
+# Documentation
-### Requirements
-- PHP 7.2+
+## Requirements
+- PHP 7.4+
- `ext-mbstring`
- - optional:
- - `ext-json`, `ext-gd`
- - `ext-imagick` with [ImageMagick](https://imagemagick.org) installed
- - [`setasign/fpdf`](https://github.com/setasign/fpdf) for the PDF output module
+ - optional:
+ - `ext-json`, `ext-gd`
+ - `ext-imagick` with [ImageMagick](https://imagemagick.org) installed
+ - [`setasign/fpdf`](https://github.com/setasign/fpdf) for the PDF output module
-### Installation
+## Installation
**requires [composer](https://getcomposer.org)**
via terminal: `composer require chillerlan/php-qrcode`
-*composer.json* (note: replace `dev-master` with a [version boundary](https://getcomposer.org/doc/articles/versions.md), e.g. `^3.2`)
+*composer.json*
```json
{
"require": {
- "php": "^7.2",
- "chillerlan/php-qrcode": "^3.4"
+ "php": "^7.4 || ^8.0",
+ "chillerlan/php-qrcode": "v4.3.x-dev#"
}
}
```
-### Usage
+Note: replace `v4.3.x-dev` with a [version constraint](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints), e.g. `^4.3` - see [releases](https://github.com/chillerlan/php-qrcode/releases) for valid versions.
+For PHP version ...
+ - 7.4+ use `^4.3`
+ - 7.2+ use `^3.4.1` (v3.4.1 also supports PHP8)
+ - 7.0+ use `^2.0`
+ - 5.6+ use `^1.0` (please let PHP 5 die!)
+
+In case you want to keep using `v4.3.x-dev`, specify the hash of a commit to avoid running into unforseen issues like so: `v4.3.x-dev#c115f7bc51d466ccb24c544e88329804aad8c2a0`
+
+PSA: [PHP 7.0 - 7.4 are EOL](https://www.php.net/supported-versions.php) and therefore the respective `QRCode` versions are also no longer supported!
+
+## Quickstart
We want to encode this URI for a mobile authenticator into a QRcode image:
```php
$data = 'otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net';
-//quick and simple:
+// quick and simple:
echo ' ';
```
-
-
+
+
Wait, what was that? Please again, slower!
-### Advanced usage
+
+## Advanced usage
Ok, step by step. First you'll need a `QRCode` instance, which can be optionally invoked with a `QROptions` (or a [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/master/src/SettingsContainerInterface.php), respectively) object as the only parameter.
@@ -92,7 +99,7 @@ $qrcode->render($data);
$qrcode->render($data, '/path/to/file.svg');
```
-In case you just want the raw QR code matrix, call `QRCode::getMatrix()` - this method is also called internally from `QRCode::render()`. See also [Custom output modules](#custom-qroutputinterface).
+In case you just want the raw QR code matrix, call `QRCode::getMatrix()` - this method is also called internally from `QRCode::render()`. See also [[Custom output interface]].
```php
$matrix = $qrcode->getMatrix($data);
@@ -102,6 +109,8 @@ foreach($matrix->matrix() as $y => $row){
// get a module's value
$value = $module;
+
+ // or via the matrix's getter method
$value = $matrix->get($x, $y);
// boolean check a module
@@ -116,88 +125,27 @@ foreach($matrix->matrix() as $y => $row){
}
```
-Have a look [in this folder](https://github.com/chillerlan/php-qrcode/tree/master/examples) for some more usage examples.
-
-#### Custom module values
-Previous versions of `QRCode` held only boolean matrix values that only allowed to determine whether a module was dark or not. Now you can distinguish between different parts of the matrix, namely the several required patterns from the QR Code specification, and use them in different ways.
-
-The dark value is the module (light) value shifted by 8 bits to the left: `$value = $M_TYPE << ($bool ? 8 : 0);`, where `$M_TYPE` is one of the `QRMatrix::M_*` constants.
-You can check the value for a type explicitly like...
-```php
-// for true (dark)
-$value >> 8 === $M_TYPE;
-
-//for false (light)
-$value === $M_TYPE;
-```
-...or you can perform a loose check, ignoring the module value
-```php
-// for true
-$value >> 8 > 0;
-
-// for false
-$value >> 8 === 0
-```
-
-See also `QRMatrix::set()`, `QRMatrix::check()` and [`QRMatrix` constants](#qrmatrix-constants).
+Have a look [in the examples folder](https://github.com/chillerlan/php-qrcode/tree/main/examples) for some more usage examples.
-To map the values and properly render the modules for the given `QROutputInterface`, it's necessary to overwrite the default values:
-```php
-$options = new QROptions;
-
-// for HTML, SVG and ImageMagick
-$options->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',
-];
+### Notes
+The QR encoder, especially the subroutines for mask pattern testing, can cause high CPU load on increased matrix size.
+You can avoid a part of this load by choosing a fast output module, like `OUTPUT_IMAGE_*` and maybe setting the mask pattern manually (which may result in unreadable QR Codes).
+Oh hey and don't forget to sanitize any user input!
-// for the image output types
-$options->moduleValues = [
- 512 => [0, 0, 0],
- // ...
-];
-// for string/text output
-$options->moduleValues = [
- 512 => '#',
- // ...
-];
-```
+## Custom output interface
-#### Custom `QROutputInterface`
-Instead of bloating your code you can simply create your own output interface by extending `QROutputAbstract`. Have a look at the [built-in output modules](https://github.com/chillerlan/php-qrcode/tree/master/src/Output).
+Instead of bloating your code you can simply create your own output interface by creating a `QROutputInterface` (i.e. extending `QROutputAbstract`).
```php
class MyCustomOutput extends QROutputAbstract{
// inherited from QROutputAbstract
- protected $matrix; // QRMatrix
- protected $moduleCount; // modules QRMatrix::size()
- protected $options; // MyCustomOptions or QROptions
- protected $scale; // scale factor from options
- protected $length; // length of the matrix ($moduleCount * $scale)
+ protected QRMatrix $matrix; // QRMatrix
+ protected int $moduleCount; // modules QRMatrix::size()
+ protected QROptions $options; // MyCustomOptions or QROptions
+ protected int $scale; // scale factor from options
+ protected int $length; // length of the matrix ($moduleCount * $scale)
// ...check/set default module values (abstract method, called by the constructor)
protected function setModuleValues():void{
@@ -219,20 +167,21 @@ class MyCustomOutput extends QROutputAbstract{
}
```
+For more examples, have a look at the [built-in output modules](https://github.com/chillerlan/php-qrcode/tree/main/src/Output).
In case you need additional settings for your output module, just extend `QROptions`...
```
class MyCustomOptions extends QROptions{
- protected $myParam = 'defaultValue';
+ protected string $myParam = 'defaultValue';
// ...
}
```
-...or use the [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/master/src/SettingsContainerInterface.php), which is the more flexible approach.
+...or use the [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/main/src/SettingsContainerInterface.php), which is the more flexible approach.
```php
trait MyCustomOptionsTrait{
- protected $myParam = 'defaultValue';
+ protected string $myParam = 'defaultValue';
// ...
}
@@ -270,123 +219,211 @@ $qrOutputInterface = new MyCustomOutput($myCustomOptions, (new QRCode($myCustomO
$qrOutputInterface->dump();
```
-### API
-
-#### `QRCode` methods
-method | return | description
------- | ------ | -----------
-`__construct(QROptions $options = null)` | - | see [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/master/src/SettingsContainerInterface.php)
-`render(string $data, string $file = null)` | mixed, `QROutputInterface::dump()` | renders a QR Code for the given `$data` and `QROptions`, saves `$file` optional
-`getMatrix(string $data)` | `QRMatrix` | returns a `QRMatrix` object for the given `$data` and current `QROptions`
-`initDataInterface(string $data)` | `QRDataInterface` | returns a fresh `QRDataInterface` for the given `$data`
-`isNumber(string $string)` | bool | checks if a string qualifies for `Number`
-`isAlphaNum(string $string)` | bool | checks if a string qualifies for `AlphaNum`
-`isKanji(string $string)` | bool | checks if a string qualifies for `Kanji`
-
-#### `QRCode` constants
-name | description
----- | -----------
-`VERSION_AUTO` | `QROptions::$version`
-`MASK_PATTERN_AUTO` | `QROptions::$maskPattern`
-`OUTPUT_MARKUP_SVG`, `OUTPUT_MARKUP_HTML` | `QROptions::$outputType` markup
-`OUTPUT_IMAGE_PNG`, `OUTPUT_IMAGE_JPG`, `OUTPUT_IMAGE_GIF` | `QROptions::$outputType` image
-`OUTPUT_STRING_JSON`, `OUTPUT_STRING_TEXT` | `QROptions::$outputType` string
-`OUTPUT_IMAGICK` | `QROptions::$outputType` ImageMagick
-`OUTPUT_FPDF` | `QROptions::$outputType` PDF, using [FPDF](https://github.com/setasign/fpdf)
-`OUTPUT_CUSTOM` | `QROptions::$outputType`, requires `QROptions::$outputInterface`
-`ECC_L`, `ECC_M`, `ECC_Q`, `ECC_H`, | ECC-Level: 7%, 15%, 25%, 30% in `QROptions::$eccLevel`
-`DATA_NUMBER`, `DATA_ALPHANUM`, `DATA_BYTE`, `DATA_KANJI` | `QRDataInterface::$datamode`
-
-#### `QROptions` properties
-property | type | default | allowed | description
--------- | ---- | ------- | ------- | -----------
-`$version` | int | `QRCode::VERSION_AUTO` | 1...40 | the [QR Code version number](http://www.qrcode.com/en/about/version.html)
-`$versionMin` | int | 1 | 1...40 | Minimum QR version (if `$version = QRCode::VERSION_AUTO`)
-`$versionMax` | int | 40 | 1...40 | Maximum QR version (if `$version = QRCode::VERSION_AUTO`)
-`$eccLevel` | int | `QRCode::ECC_L` | `QRCode::ECC_X` | Error correct level, where X = L (7%), M (15%), Q (25%), H (30%)
-`$maskPattern` | int | `QRCode::MASK_PATTERN_AUTO` | 0...7 | Mask Pattern to use
-`$addQuietzone` | bool | `true` | - | Add a "quiet zone" (margin) according to the QR code spec
-`$quietzoneSize` | int | 4 | clamped to 0 ... `$matrixSize / 2` | Size of the quiet zone
-`$dataMode` | string | `null` | `Number`, `AlphaNum`, `Kanji`, `Byte` | allows overriding the data type detection
-`$outputType` | string | `QRCode::OUTPUT_IMAGE_PNG` | `QRCode::OUTPUT_*` | built-in output type
-`$outputInterface` | string | `null` | * | FQCN of the custom `QROutputInterface` if `QROptions::$outputType` is set to `QRCode::OUTPUT_CUSTOM`
-`$cachefile` | string | `null` | * | optional cache file path
-`$eol` | string | `PHP_EOL` | * | newline string (HTML, SVG, TEXT)
-`$scale` | int | 5 | * | size of a QR code pixel (SVG, IMAGE_*), HTML -> via CSS
-`$cssClass` | string | `null` | * | a common css class
-`$svgOpacity` | float | 1.0 | 0...1 |
-`$svgDefs` | string | * | * | anything between [``](https://developer.mozilla.org/docs/Web/SVG/Element/defs)
-`$svgViewBoxSize` | int | `null` | * | a positive integer which defines width/height of the [viewBox attribute](https://css-tricks.com/scale-svg/#article-header-id-3)
-`$textDark` | string | '🔴' | * | string substitute for dark
-`$textLight` | string | '⭕' | * | string substitute for light
-`$markupDark` | string | '#000' | * | markup substitute for dark (CSS value)
-`$markupLight` | string | '#fff' | * | markup substitute for light (CSS value)
-`$imageBase64` | bool | `true` | - | whether to return the image data as base64 or raw like from `file_get_contents()`
-`$imageTransparent` | bool | `true` | - | toggle transparency (no jpeg support)
-`$imageTransparencyBG` | array | `[255, 255, 255]` | `[R, G, B]` | the RGB values for the transparent color, see [`imagecolortransparent()`](http://php.net/manual/function.imagecolortransparent.php)
-`$pngCompression` | int | -1 | -1 ... 9 | `imagepng()` compression level, -1 = auto
-`$jpegQuality` | int | 85 | 0 - 100 | `imagejpeg()` quality
-`$imagickFormat` | string | 'png' | * | ImageMagick output type, see `Imagick::setType()`
-`$imagickBG` | string | `null` | * | ImageMagick background color, see `ImagickPixel::__construct()`
-`$moduleValues` | array | `null` | * | Module values map, see [Custom output modules](#custom-qroutputinterface) and `QROutputInterface::DEFAULT_MODULE_VALUES`
-
-#### `QRMatrix` methods
-method | return | description
------- | ------ | -----------
-`__construct(int $version, int $eclevel)` | - | -
-`matrix()` | array | the internal matrix representation as a 2 dimensional array
-`version()` | int | the current QR Code version
-`eccLevel()` | int | current ECC level
-`maskPattern()` | int | the used mask pattern
-`size()` | int | the absoulute size of the matrix, including quiet zone (if set). `$version * 4 + 17 + 2 * $quietzone`
-`get(int $x, int $y)` | int | returns the value of the module
-`set(int $x, int $y, bool $value, int $M_TYPE)` | `QRMatrix` | sets the `$M_TYPE` value for the module
-`check(int $x, int $y)` | bool | checks whether a module is true (dark) or false (light)
-`setLogoSpace(int $width, int $height, int $startX = null, int $startY = null)` | `QRMatrix` | creates a logo space in the matrix
-
-#### `QRMatrix` constants
-name | light (false) | dark (true) | description
----- | ------------- | ----------- | -----------
-`M_NULL` | 0 | - | module not set (should never appear. if so, there's an error)
-`M_DARKMODULE` | - | 512 | once per matrix at `$xy = [8, 4 * $version + 9]`
-`M_DATA` | 4 | 1024 | the actual encoded data
-`M_FINDER` | 6 | 1536 | the 7x7 finder patterns
-`M_SEPARATOR` | 8 | - | separator lines around the finder patterns
-`M_ALIGNMENT` | 10 | 2560 | the 5x5 alignment patterns
-`M_TIMING` | 12 | 3072 | the timing pattern lines
-`M_FORMAT` | 14 | 3584 | format information pattern
-`M_VERSION` | 16 | 4096 | version information pattern
-`M_QUIETZONE` | 18 | - | margin around the QR Code
-`M_LOGO` | 20 | - | space for a logo image (not used yet)
-`M_TEST` | 255 | 65280 | test value
+### Custom module values
+You can distinguish between different parts of the matrix, namely the several required patterns from the QR Code specification, and use them in different ways, i.e. to assign different colors for each part of the matrix (see the [image example](https://github.com/chillerlan/php-qrcode/blob/main/examples/image.php)).
+The dark value is the module value (light) shifted by 8 bits to the left: `$value = $M_TYPE << ($bool ? 8 : 0);`, where `$M_TYPE` is one of the `QRMatrix::M_*` constants.
+You can check the value for a type explicitly like...
+```php
+// for true (dark)
+($value >> 8) === $M_TYPE;
-### Notes
-The QR encoder, especially the subroutines for mask pattern testing, can cause high CPU load on increased matrix size.
-You can avoid a part of this load by choosing a fast output module, like `OUTPUT_IMAGE_*` and setting the mask pattern manually (which may result in unreadable QR Codes).
-Oh hey and don't forget to sanitize any user input!
+// for false (light)
+$value === $M_TYPE;
+```
+...or you can perform a loose check, ignoring the module value
+```php
+// for true
+($value >> 8) > 0;
-### Disclaimer!
-I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk!
+// for false
+($value >> 8) === 0;
+```
-#### Trademark Notice
+See also `QRMatrix::set()`, `QRMatrix::check()` and [`QRMatrix` constants](#qrmatrix-constants).
-The word "QR Code" is registered trademark of *DENSO WAVE INCORPORATED*
-http://www.denso-wave.com/qrcode/faqpatent-e.html
+To map the values and properly render the modules for the given `QROutputInterface`, it's necessary to overwrite the default values:
+```php
+$options = new QROptions;
-### Framework Integration
-- Drupal [Google Authenticator Login `ga_login`](https://www.drupal.org/project/ga_login)
-- WordPress [`wp-two-factor-auth`](https://github.com/sjinks/wp-two-factor-auth)
-- WordPress [Simple 2FA `simple-2fa`](https://wordpress.org/plugins/simple-2fa/)
-- WoltLab Suite [two-step-verification](http://pluginstore.woltlab.com/file/3007-two-step-verification/)
-- [Cachet](https://github.com/CachetHQ/Cachet)
+// for HTML, SVG and ImageMagick
+$options->moduleValues = [
+ // finder
+ QRMatrix::M_FINDER_DARK => '#A71111', // dark (true)
+ QRMatrix::M_FINDER_DOT_DARK => '#A71111', // dark (true)
+ QRMatrix::M_FINDER => '#FFBFBF', // light (false)
+ // alignment
+ QRMatrix::M_ALIGNMENT_DARK => '#A70364',
+ QRMatrix::M_ALIGNMENT => '#FFC9C9',
+ // timing
+ QRMatrix::M_TIMING_DARK => '#98005D',
+ QRMatrix::M_TIMING => '#FFB8E9',
+ // format
+ QRMatrix::M_FORMAT_DARK => '#003804',
+ QRMatrix::M_FORMAT => '#00FB12',
+ // version
+ QRMatrix::M_VERSION_DARK => '#650098',
+ QRMatrix::M_VERSION => '#E0B8FF',
+ // data
+ QRMatrix::M_DATA_DARK => '#4A6000',
+ QRMatrix::M_DATA => '#ECF9BE',
+ // darkmodule
+ QRMatrix::M_DARKMODULE_DARK => '#080063',
+ // separator
+ QRMatrix::M_SEPARATOR => '#AFBFBF',
+ // quietzone
+ QRMatrix::M_QUIETZONE => '#FFFFFF',
+];
+
+// for the image output types
+$options->moduleValues = [
+ QRMatrix::M_DATA_DARK => [0, 0, 0],
+ // ...
+];
+
+// for string/text output
+$options->moduleValues = [
+ QRMatrix::M_DATA_DARK => '#',
+ // ...
+];
+```
+
+
+## Public API
+
+### `QRCode` API
+#### Methods
+| method | return | description |
+|---------------------------------------------|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------|
+| `__construct(QROptions $options = null)` | - | see [`SettingsContainerInterface`](https://github.com/chillerlan/php-settings-container/blob/main/src/SettingsContainerInterface.php) |
+| `render(string $data, string $file = null)` | mixed, `QROutputInterface::dump()` | renders a QR Code for the given `$data` and `QROptions`, saves `$file` optional |
+| `getMatrix(string $data)` | `QRMatrix` | returns a `QRMatrix` object for the given `$data` and current `QROptions` |
+| `initDataInterface(string $data)` | `QRDataInterface` | returns a fresh `QRDataInterface` for the given `$data` |
+| `isNumber(string $string)` | bool | checks if a string qualifies for `Number` |
+| `isAlphaNum(string $string)` | bool | checks if a string qualifies for `AlphaNum` |
+| `isKanji(string $string)` | bool | checks if a string qualifies for `Kanji` |
+| `isByte(string $string)` | bool | checks if a string is non-empty |
+
+#### Constants
+| name | description |
+|------------------------------------------------------------|------------------------------------------------------------------------------|
+| `VERSION_AUTO` | `QROptions::$version` |
+| `MASK_PATTERN_AUTO` | `QROptions::$maskPattern` |
+| `OUTPUT_MARKUP_SVG`, `OUTPUT_MARKUP_HTML` | `QROptions::$outputType` markup |
+| `OUTPUT_IMAGE_PNG`, `OUTPUT_IMAGE_JPG`, `OUTPUT_IMAGE_GIF` | `QROptions::$outputType` image |
+| `OUTPUT_STRING_JSON`, `OUTPUT_STRING_TEXT` | `QROptions::$outputType` string |
+| `OUTPUT_IMAGICK` | `QROptions::$outputType` ImageMagick |
+| `OUTPUT_FPDF` | `QROptions::$outputType` PDF, using [FPDF](https://github.com/setasign/fpdf) |
+| `OUTPUT_CUSTOM` | `QROptions::$outputType`, requires `QROptions::$outputInterface` |
+| `ECC_L`, `ECC_M`, `ECC_Q`, `ECC_H`, | ECC-Level: 7%, 15%, 25%, 30% in `QROptions::$eccLevel` |
+| `DATA_NUMBER`, `DATA_ALPHANUM`, `DATA_BYTE`, `DATA_KANJI` | `QRDataInterface::$datamode` |
+
+### `QRMatrix` API
+
+#### Methods
+| method | return | description |
+|-------------------------------------------------|------------|-------------------------------------------------------------------------------------------------------|
+| `__construct(int $version, int $eclevel)` | - | - |
+| `init(int $maskPattern, bool $test = null)` | `QRMatrix` | |
+| `matrix()` | array | the internal matrix representation as a 2 dimensional array |
+| `version()` | int | the current QR Code version |
+| `eccLevel()` | int | current ECC level |
+| `maskPattern()` | int | the used mask pattern |
+| `size()` | int | the absoulute size of the matrix, including quiet zone (if set). `$version * 4 + 17 + 2 * $quietzone` |
+| `get(int $x, int $y)` | int | returns the value of the module |
+| `set(int $x, int $y, bool $value, int $M_TYPE)` | `QRMatrix` | sets the `$M_TYPE` value for the module |
+| `check(int $x, int $y)` | bool | checks whether a module is true (dark) or false (light) |
+
+#### Constants
+| name | description |
+|----------------------|---------------------------------------------------------------|
+| `M_NULL` | module not set (should never appear. if so, there's an error) |
+| `M_DARKMODULE` | once per matrix at `$xy = [8, 4 * $version + 9]` |
+| `M_DARKMODULE_LIGHT` | (reserved for reflectance reversal) |
+| `M_DATA` | the actual encoded data |
+| `M_DATA_DARK` | |
+| `M_FINDER` | the 7x7 finder patterns |
+| `M_FINDER_DARK` | |
+| `M_FINDER_DOT` | the 3x3 dot inside the finder patterns |
+| `M_FINDER_DOT_LIGHT` | (reserved for reflectance reversal) |
+| `M_SEPARATOR` | separator lines around the finder patterns |
+| `M_SEPARATOR_DARK` | (reserved for reflectance reversal) |
+| `M_ALIGNMENT` | the 5x5 alignment patterns |
+| `M_ALIGNMENT_DARK` | |
+| `M_TIMING` | the timing pattern lines |
+| `M_TIMING_DARK` | |
+| `M_FORMAT` | format information pattern |
+| `M_FORMAT_DARK` | |
+| `M_VERSION` | version information pattern |
+| `M_VERSION_DARK` | |
+| `M_QUIETZONE` | margin around the QR Code |
+| `M_QUIETZONE_DARK` | (reserved for reflectance reversal) |
+| `M_LOGO` | space for a logo image |
+| `M_LOGO_DARK` | (reserved for reflectance reversal) |
+
+### `QROptions` API
+
+#### Properties
+| property | type | default | allowed | description |
+|------------------------|--------|-----------------------------|---------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
+| `$version` | int | `QRCode::VERSION_AUTO` | 1...40 | the [QR Code version number](http://www.qrcode.com/en/about/version.html) |
+| `$versionMin` | int | 1 | 1...40 | Minimum QR version (if `$version = QRCode::VERSION_AUTO`) |
+| `$versionMax` | int | 40 | 1...40 | Maximum QR version (if `$version = QRCode::VERSION_AUTO`) |
+| `$eccLevel` | int | `QRCode::ECC_L` | `QRCode::ECC_X` | Error correct level, where X = L (7%), M (15%), Q (25%), H (30%) |
+| `$maskPattern` | int | `QRCode::MASK_PATTERN_AUTO` | 0...7 | Mask Pattern to use |
+| `$addQuietzone` | bool | `true` | - | Add a "quiet zone" (margin) according to the QR code spec |
+| `$quietzoneSize` | int | 4 | clamped to 0 ... `$matrixSize / 2` | Size of the quiet zone |
+| `$dataModeOverride` | string | `null` | `Number`, `AlphaNum`, `Kanji`, `Byte` | allows overriding the data type detection |
+| `$outputType` | string | `QRCode::OUTPUT_IMAGE_PNG` | `QRCode::OUTPUT_*` | built-in output type |
+| `$outputInterface` | string | `null` | * | FQCN of the custom `QROutputInterface` if `QROptions::$outputType` is set to `QRCode::OUTPUT_CUSTOM` |
+| `$cachefile` | string | `null` | * | optional cache file path |
+| `$eol` | string | `PHP_EOL` | * | newline string (HTML, SVG, TEXT) |
+| `$scale` | int | 5 | * | size of a QR code pixel (SVG, IMAGE_*), HTML -> via CSS |
+| `$cssClass` | string | `null` | * | a common css class |
+| `$svgOpacity` | float | 1.0 | 0...1 | |
+| `$svgDefs` | string | * | * | anything between [``](https://developer.mozilla.org/docs/Web/SVG/Element/defs) |
+| `$svgViewBoxSize` | int | `null` | * | a positive integer which defines width/height of the [viewBox attribute](https://css-tricks.com/scale-svg/#article-header-id-3) |
+| `$textDark` | string | '██' | * | string substitute for dark |
+| `$textLight` | string | '░░' | * | string substitute for light |
+| `$markupDark` | string | '#000' | * | markup substitute for dark (CSS value) |
+| `$markupLight` | string | '#fff' | * | markup substitute for light (CSS value) |
+| `$imageBase64` | bool | `true` | - | whether to return the image data as base64 or raw like from `file_get_contents()` |
+| `$imageTransparent` | bool | `true` | - | toggle transparency (no jpeg support) |
+| `$imageTransparencyBG` | array | `[255, 255, 255]` | `[R, G, B]` | the RGB values for the transparent color, see [`imagecolortransparent()`](http://php.net/manual/function.imagecolortransparent.php) |
+| `$pngCompression` | int | -1 | -1 ... 9 | `imagepng()` compression level, -1 = auto |
+| `$jpegQuality` | int | 85 | 0 - 100 | `imagejpeg()` quality |
+| `$imagickFormat` | string | 'png' | * | ImageMagick output type, see `Imagick::setType()` |
+| `$imagickBG` | string | `null` | * | ImageMagick background color, see `ImagickPixel::__construct()` |
+| `$moduleValues` | array | `null` | * | Module values map, see [[Custom output interface]] and `QROutputInterface::DEFAULT_MODULE_VALUES` |
+
+## Framework Integration
+- Drupal:
+ - [Google Authenticator Login `ga_login`](https://www.drupal.org/project/ga_login)
+- Symfony
+ - [phpqrcode-bundle](https://github.com/jonasarts/phpqrcode-bundle)
+- WordPress:
+ - [`wp-two-factor-auth`](https://github.com/sjinks/wp-two-factor-auth)
+ - [`simple-2fa`](https://wordpress.org/plugins/simple-2fa/)
+ - [`wordpress-seo`](https://github.com/Yoast/wordpress-seo)
+ - [`floating-share-button`](https://github.com/qriouslad/floating-share-button)
+- WoltLab Suite
+ - [two-step-verification](http://pluginstore.woltlab.com/file/3007-two-step-verification/)
- [Appwrite](https://github.com/appwrite/appwrite)
+- [Cachet](https://github.com/CachetHQ/Cachet)
+- [twill](https://github.com/area17/twill)
- other uses: [dependents](https://github.com/chillerlan/php-qrcode/network/dependents) / [packages](https://github.com/chillerlan/php-qrcode/network/dependents?dependent_type=PACKAGE)
-
+## Shameless advertising
Hi, please check out my other projects that are way cooler than qrcodes!
- [php-oauth-core](https://github.com/chillerlan/php-oauth-core) - an OAuth 1/2 client library along with a bunch of [providers](https://github.com/chillerlan/php-oauth-providers)
- [php-httpinterface](https://github.com/chillerlan/php-httpinterface) - a PSR-7/15/17/18 implemetation
- [php-database](https://github.com/chillerlan/php-database) - a database client & querybuilder for MySQL, Postgres, SQLite, MSSQL, Firebird
+## Disclaimer!
+I don't take responsibility for molten CPUs, misled applications, failed log-ins etc.. Use at your own risk!
+
+### Trademark Notice
+
+The word "QR Code" is a registered trademark of *DENSO WAVE INCORPORATED*
+https://www.qrcode.com/en/faq.html#patentH2Title
diff --git a/vendor/chillerlan/php-qrcode/composer.json b/vendor/chillerlan/php-qrcode/composer.json
index c2299a3..97d8bbe 100644
--- a/vendor/chillerlan/php-qrcode/composer.json
+++ b/vendor/chillerlan/php-qrcode/composer.json
@@ -1,6 +1,6 @@
{
"name": "chillerlan/php-qrcode",
- "description": "A QR code generator. PHP 7.2+",
+ "description": "A QR code generator with a user friendly API. PHP 7.4+",
"homepage": "https://github.com/chillerlan/php-qrcode",
"license": "MIT",
"minimum-stability": "stable",
@@ -24,17 +24,21 @@
}
],
"require": {
- "php": "^7.2",
+ "php": "^7.4 || ^8.0",
"ext-mbstring": "*",
- "chillerlan/php-settings-container": "^1.2"
+ "chillerlan/php-settings-container": "^2.1.4 || ^3.1"
},
"require-dev": {
- "phpunit/phpunit": "^8.5",
- "setasign/fpdf": "^1.8.2"
+ "phan/phan": "^5.4",
+ "phpmd/phpmd": "^2.15",
+ "phpunit/phpunit": "^9.6",
+ "setasign/fpdf": "^1.8.2",
+ "squizlabs/php_codesniffer": "^3.8"
},
"suggest": {
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
- "setasign/fpdf": "Required to use the QR FPDF output."
+ "setasign/fpdf": "Required to use the QR FPDF output.",
+ "simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code"
},
"autoload": {
"psr-4": {
@@ -43,9 +47,16 @@
},
"autoload-dev": {
"psr-4": {
- "chillerlan\\QRCodePublic\\": "public/",
- "chillerlan\\QRCodeTest\\": "tests/",
- "chillerlan\\QRCodeExamples\\": "examples/"
+ "chillerlan\\QRCodeTest\\": "tests/"
}
+ },
+ "scripts": {
+ "phpunit": "@php vendor/bin/phpunit",
+ "phan": "@php vendor/bin/phan"
+ },
+ "config": {
+ "lock": false,
+ "sort-packages": true,
+ "platform-check": true
}
}
diff --git a/vendor/chillerlan/php-qrcode/examples/MyCustomOutput.php b/vendor/chillerlan/php-qrcode/examples/MyCustomOutput.php
deleted file mode 100644
index 3c01f86..0000000
--- a/vendor/chillerlan/php-qrcode/examples/MyCustomOutput.php
+++ /dev/null
@@ -1,36 +0,0 @@
-
- * @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;
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/examples/QRImageWithLogo.php b/vendor/chillerlan/php-qrcode/examples/QRImageWithLogo.php
deleted file mode 100644
index f9d94ae..0000000
--- a/vendor/chillerlan/php-qrcode/examples/QRImageWithLogo.php
+++ /dev/null
@@ -1,81 +0,0 @@
-
- * @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->logoWidth,
- $this->options->logoHeight
- // 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
- $lw = ($this->options->logoWidth - 2) * $this->options->scale;
- $lh = ($this->options->logoHeight - 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;
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/examples/QRImageWithText.php b/vendor/chillerlan/php-qrcode/examples/QRImageWithText.php
deleted file mode 100644
index 5ca572f..0000000
--- a/vendor/chillerlan/php-qrcode/examples/QRImageWithText.php
+++ /dev/null
@@ -1,104 +0,0 @@
-
- * @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);
- }
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/examples/custom_output.php b/vendor/chillerlan/php-qrcode/examples/custom_output.php
deleted file mode 100644
index 71ea626..0000000
--- a/vendor/chillerlan/php-qrcode/examples/custom_output.php
+++ /dev/null
@@ -1,38 +0,0 @@
-
- * @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));
diff --git a/vendor/chillerlan/php-qrcode/examples/example_image.png b/vendor/chillerlan/php-qrcode/examples/example_image.png
deleted file mode 100644
index b4a80f2..0000000
Binary files a/vendor/chillerlan/php-qrcode/examples/example_image.png and /dev/null differ
diff --git a/vendor/chillerlan/php-qrcode/examples/example_svg.png b/vendor/chillerlan/php-qrcode/examples/example_svg.png
deleted file mode 100644
index f1e7b32..0000000
Binary files a/vendor/chillerlan/php-qrcode/examples/example_svg.png and /dev/null differ
diff --git a/vendor/chillerlan/php-qrcode/examples/fpdf.php b/vendor/chillerlan/php-qrcode/examples/fpdf.php
deleted file mode 100644
index 9c690a7..0000000
--- a/vendor/chillerlan/php-qrcode/examples/fpdf.php
+++ /dev/null
@@ -1,47 +0,0 @@
- 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);
diff --git a/vendor/chillerlan/php-qrcode/examples/html.php b/vendor/chillerlan/php-qrcode/examples/html.php
deleted file mode 100644
index aa5305d..0000000
--- a/vendor/chillerlan/php-qrcode/examples/html.php
+++ /dev/null
@@ -1,102 +0,0 @@
-
- * @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');
-
-?>
-
-
-
-
-
- QRCode test
-
-
-
-
- 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);
-
-?>
-
-
-
-
-
-
diff --git a/vendor/chillerlan/php-qrcode/examples/image.php b/vendor/chillerlan/php-qrcode/examples/image.php
deleted file mode 100644
index 89ba2a9..0000000
--- a/vendor/chillerlan/php-qrcode/examples/image.php
+++ /dev/null
@@ -1,60 +0,0 @@
-
- * @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);
-
-
-
-
-
diff --git a/vendor/chillerlan/php-qrcode/examples/imageWithLogo.php b/vendor/chillerlan/php-qrcode/examples/imageWithLogo.php
deleted file mode 100644
index 987e10c..0000000
--- a/vendor/chillerlan/php-qrcode/examples/imageWithLogo.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- * @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 $logoWidth
- * @property int $logoHeight
- *
- * @noinspection PhpIllegalPsrClassPathInspection
- */
-class LogoOptions extends QROptions{
- protected $logoWidth;
- protected $logoHeight;
-}
-
-$options = new LogoOptions;
-
-$options->version = 7;
-$options->eccLevel = QRCode::ECC_H;
-$options->imageBase64 = false;
-$options->logoWidth = 13;
-$options->logoHeight = 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');
diff --git a/vendor/chillerlan/php-qrcode/examples/imageWithText.php b/vendor/chillerlan/php-qrcode/examples/imageWithText.php
deleted file mode 100644
index 050781c..0000000
--- a/vendor/chillerlan/php-qrcode/examples/imageWithText.php
+++ /dev/null
@@ -1,33 +0,0 @@
-
- * @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');
diff --git a/vendor/chillerlan/php-qrcode/examples/imagick.php b/vendor/chillerlan/php-qrcode/examples/imagick.php
deleted file mode 100644
index 6bec4d0..0000000
--- a/vendor/chillerlan/php-qrcode/examples/imagick.php
+++ /dev/null
@@ -1,59 +0,0 @@
-
- * @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);
-
-
-
-
-
diff --git a/vendor/chillerlan/php-qrcode/examples/octocat.png b/vendor/chillerlan/php-qrcode/examples/octocat.png
deleted file mode 100644
index f9050b9..0000000
Binary files a/vendor/chillerlan/php-qrcode/examples/octocat.png and /dev/null differ
diff --git a/vendor/chillerlan/php-qrcode/examples/svg.php b/vendor/chillerlan/php-qrcode/examples/svg.php
deleted file mode 100644
index a7a159d..0000000
--- a/vendor/chillerlan/php-qrcode/examples/svg.php
+++ /dev/null
@@ -1,77 +0,0 @@
-
- * @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' => '
-
-
-
-
-
-
-
-
- ',
- '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;
-
-
diff --git a/vendor/chillerlan/php-qrcode/examples/text.php b/vendor/chillerlan/php-qrcode/examples/text.php
deleted file mode 100644
index 9bdf154..0000000
--- a/vendor/chillerlan/php-qrcode/examples/text.php
+++ /dev/null
@@ -1,68 +0,0 @@
-
- * @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,
-]);
-
-// to view it in a browser
-echo ''.(new QRCode($options))->render($data).' ';
-
-
-// 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',
- ],
-]);
-
-// to view it in a browser
-echo ''.(new QRCode($options))->render($data).' ';
-
-
-
-
-
diff --git a/vendor/chillerlan/php-qrcode/phpdoc.xml b/vendor/chillerlan/php-qrcode/phpdoc.xml
deleted file mode 100644
index d191e98..0000000
--- a/vendor/chillerlan/php-qrcode/phpdoc.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
- public/docs
-
-
- public/docs
-
-
- src
-
-
-
-
-
\ No newline at end of file
diff --git a/vendor/chillerlan/php-qrcode/phpmd.xml b/vendor/chillerlan/php-qrcode/phpmd.xml
deleted file mode 100644
index a70f7e3..0000000
--- a/vendor/chillerlan/php-qrcode/phpmd.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
- codemasher/php-qrcode PMD ruleset
- */examples/*
- */tests/*
-
-
-
-
- 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/vendor/chillerlan/php-qrcode/phpunit.xml b/vendor/chillerlan/php-qrcode/phpunit.xml
deleted file mode 100644
index 3a9b678..0000000
--- a/vendor/chillerlan/php-qrcode/phpunit.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- ./src
-
-
-
-
- ./tests/
-
-
-
-
-
-
-
-
diff --git a/vendor/chillerlan/php-qrcode/public/index.html b/vendor/chillerlan/php-qrcode/public/index.html
deleted file mode 100644
index d7bf6c8..0000000
--- a/vendor/chillerlan/php-qrcode/public/index.html
+++ /dev/null
@@ -1,163 +0,0 @@
-
-
-
-
-
- QR Code Generator
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/vendor/chillerlan/php-qrcode/public/qrcode.php b/vendor/chillerlan/php-qrcode/public/qrcode.php
deleted file mode 100644
index 1f8427c..0000000
--- a/vendor/chillerlan/php-qrcode/public/qrcode.php
+++ /dev/null
@@ -1,97 +0,0 @@
-
- * @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 = ' ';
- }
- elseif($_POST['output_type'] === 'text'){
- $qrcode = ''.$qrcode.' ';
- }
- elseif($_POST['output_type'] === 'json'){
- $qrcode = ''.$qrcode.' ';
- }
-
- 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;
-}
diff --git a/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php b/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
index c6d34e7..28d9d75 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/AlphaNum.php
@@ -14,22 +14,19 @@
use chillerlan\QRCode\QRCode;
-use function array_search, ord, sprintf;
+use function ord, sprintf;
/**
* Alphanumeric mode: 0 to 9, A to Z, space, $ % * + - . / :
+ *
+ * ISO/IEC 18004:2000 Section 8.3.3
+ * ISO/IEC 18004:2000 Section 8.4.3
*/
-class AlphaNum extends QRDataAbstract{
+final class AlphaNum extends QRDataAbstract{
- /**
- * @inheritdoc
- */
- protected $datamode = QRCode::DATA_ALPHANUM;
+ protected int $datamode = QRCode::DATA_ALPHANUM;
- /**
- * @inheritdoc
- */
- protected $lengthBits = [9, 11, 13];
+ protected array $lengthBits = [9, 11, 13];
/**
* @inheritdoc
@@ -47,19 +44,17 @@ protected function write(string $data):void{
}
/**
- * @param string $chr
+ * get the code for the given character
*
- * @return int
- * @throws \chillerlan\QRCode\Data\QRCodeDataException
+ * @throws \chillerlan\QRCode\Data\QRCodeDataException on an illegal character occurence
*/
protected function getCharCode(string $chr):int{
- $i = array_search($chr, $this::ALPHANUM_CHAR_MAP);
- if($i !== false){
- return $i;
+ if(!isset($this::CHAR_MAP_ALPHANUM[$chr])){
+ throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $chr, ord($chr)));
}
- throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $chr, ord($chr)));
+ return $this::CHAR_MAP_ALPHANUM[$chr];
}
}
diff --git a/vendor/chillerlan/php-qrcode/src/Data/Byte.php b/vendor/chillerlan/php-qrcode/src/Data/Byte.php
index f195564..02e76a6 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/Byte.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/Byte.php
@@ -18,18 +18,15 @@
/**
* Byte mode, ISO-8859-1 or UTF-8
+ *
+ * ISO/IEC 18004:2000 Section 8.3.4
+ * ISO/IEC 18004:2000 Section 8.4.4
*/
-class Byte extends QRDataAbstract{
+final class Byte extends QRDataAbstract{
- /**
- * @inheritdoc
- */
- protected $datamode = QRCode::DATA_BYTE;
+ protected int $datamode = QRCode::DATA_BYTE;
- /**
- * @inheritdoc
- */
- protected $lengthBits = [8, 16, 16];
+ protected array $lengthBits = [8, 16, 16];
/**
* @inheritdoc
diff --git a/vendor/chillerlan/php-qrcode/src/Data/Kanji.php b/vendor/chillerlan/php-qrcode/src/Data/Kanji.php
index ce600d4..e106c50 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/Kanji.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/Kanji.php
@@ -18,18 +18,15 @@
/**
* Kanji mode: double-byte characters from the Shift JIS character set
+ *
+ * ISO/IEC 18004:2000 Section 8.3.5
+ * ISO/IEC 18004:2000 Section 8.4.5
*/
-class Kanji extends QRDataAbstract{
+final class Kanji extends QRDataAbstract{
- /**
- * @inheritdoc
- */
- protected $datamode = QRCode::DATA_KANJI;
+ protected int $datamode = QRCode::DATA_KANJI;
- /**
- * @inheritdoc
- */
- protected $lengthBits = [8, 10, 12];
+ protected array $lengthBits = [8, 10, 12];
/**
* @inheritdoc
@@ -40,6 +37,8 @@ protected function getLength(string $data):int{
/**
* @inheritdoc
+ *
+ * @throws \chillerlan\QRCode\Data\QRCodeDataException on an illegal character occurence
*/
protected function write(string $data):void{
$len = strlen($data);
@@ -47,17 +46,17 @@ protected function write(string $data):void{
for($i = 0; $i + 1 < $len; $i += 2){
$c = ((0xff & ord($data[$i])) << 8) | (0xff & ord($data[$i + 1]));
- if(0x8140 <= $c && $c <= 0x9FFC){
+ if($c >= 0x8140 && $c <= 0x9FFC){
$c -= 0x8140;
}
- elseif(0xE040 <= $c && $c <= 0xEBBF){
+ elseif($c >= 0xE040 && $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);
+ $this->bitBuffer->put(((($c >> 8) & 0xff) * 0xC0) + ($c & 0xff), 13);
}
diff --git a/vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php b/vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php
index 8dfd241..959892b 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/MaskPatternTester.php
@@ -8,41 +8,51 @@
* @author Smiley
* @copyright 2017 Smiley
* @license MIT
+ *
+ * @noinspection PhpUnused
*/
namespace chillerlan\QRCode\Data;
-use function abs, call_user_func_array;
+use function abs, array_search, call_user_func_array, min;
/**
- * The sole purpose of this class is to receive a QRMatrix object and run the pattern tests on it.
+ * Receives a QRDataInterface object and runs the mask pattern tests on it.
+ *
+ * ISO/IEC 18004:2000 Section 8.8.2 - Evaluation of masking results
*
- * @link http://www.thonky.com/qr-code-tutorial/data-masking
+ * @see http://www.thonky.com/qr-code-tutorial/data-masking
*/
-class MaskPatternTester{
-
- /**
- * @var \chillerlan\QRCode\Data\QRMatrix
- */
- protected $matrix;
+final class MaskPatternTester{
/**
- * @var int
+ * The data interface that contains the data matrix to test
*/
- protected $moduleCount;
+ protected QRDataInterface $dataInterface;
/**
- * Receives the matrix an sets the module count
+ * Receives the QRDataInterface
*
* @see \chillerlan\QRCode\QROptions::$maskPattern
* @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
- * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
+ */
+ public function __construct(QRDataInterface $dataInterface){
+ $this->dataInterface = $dataInterface;
+ }
+
+ /**
+ * shoves a QRMatrix through the MaskPatternTester to find the lowest penalty mask pattern
*
- * @param \chillerlan\QRCode\Data\QRMatrix $matrix
+ * @see \chillerlan\QRCode\Data\MaskPatternTester
*/
- public function __construct(QRMatrix $matrix){
- $this->matrix = $matrix;
- $this->moduleCount = $this->matrix->size();
+ public function getBestMaskPattern():int{
+ $penalties = [];
+
+ for($pattern = 0; $pattern < 8; $pattern++){
+ $penalties[$pattern] = $this->testPattern($pattern);
+ }
+
+ return array_search(min($penalties), $penalties, true);
}
/**
@@ -50,15 +60,13 @@ public function __construct(QRMatrix $matrix){
*
* @see \chillerlan\QRCode\QROptions::$maskPattern
* @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
- * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
- *
- * @return int
*/
- public function testPattern():int{
- $penalty = 0;
+ public function testPattern(int $pattern):int{
+ $matrix = $this->dataInterface->initMatrix($pattern, true);
+ $penalty = 0;
for($level = 1; $level <= 4; $level++){
- $penalty += call_user_func_array([$this, 'testLevel'.$level], [$this->matrix->matrix(true)]);
+ $penalty += call_user_func_array([$this, 'testLevel'.$level], [$matrix->matrix(true), $matrix->size()]);
}
return (int)$penalty;
@@ -66,10 +74,8 @@ public function testPattern():int{
/**
* Checks for each group of five or more same-colored modules in a row (or column)
- *
- * @return int
*/
- protected function testLevel1(array $m):int{
+ protected function testLevel1(array $m, int $size):int{
$penalty = 0;
foreach($m as $y => $row){
@@ -78,13 +84,13 @@ protected function testLevel1(array $m):int{
for($ry = -1; $ry <= 1; $ry++){
- if($y + $ry < 0 || $this->moduleCount <= $y + $ry){
+ if($y + $ry < 0 || $size <= $y + $ry){
continue;
}
for($rx = -1; $rx <= 1; $rx++){
- if(($ry === 0 && $rx === 0) || (($x + $rx) < 0 || $this->moduleCount <= ($x + $rx))){
+ if(($ry === 0 && $rx === 0) || (($x + $rx) < 0 || $size <= ($x + $rx))){
continue;
}
@@ -107,26 +113,24 @@ protected function testLevel1(array $m):int{
/**
* Checks for each 2x2 area of same-colored modules in the matrix
- *
- * @return int
*/
- protected function testLevel2(array $m):int{
+ protected function testLevel2(array $m, int $size):int{
$penalty = 0;
foreach($m as $y => $row){
- if($y > ($this->moduleCount - 2)){
+ if($y > $size - 2){
break;
}
foreach($row as $x => $val){
- if($x > ($this->moduleCount - 2)){
+ if($x > $size - 2){
break;
}
if(
- $val === $m[$y][$x + 1]
+ $val === $row[$x + 1]
&& $val === $m[$y + 1][$x]
&& $val === $m[$y + 1][$x + 1]
){
@@ -140,30 +144,28 @@ protected function testLevel2(array $m):int{
/**
* 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{
+ protected function testLevel3(array $m, int $size):int{
$penalties = 0;
foreach($m as $y => $row){
foreach($row as $x => $val){
if(
- ($x + 6) < $this->moduleCount
+ $x + 6 < $size
&& $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]
+ && !$row[$x + 1]
+ && $row[$x + 2]
+ && $row[$x + 3]
+ && $row[$x + 4]
+ && !$row[$x + 5]
+ && $row[$x + 6]
){
$penalties++;
}
if(
- ($y + 6) < $this->moduleCount
+ $y + 6 < $size
&& $val
&& !$m[$y + 1][$x]
&& $m[$y + 2][$x]
@@ -183,21 +185,19 @@ protected function testLevel3(array $m):int{
/**
* 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{
+ protected function testLevel4(array $m, int $size):float{
$count = 0;
- foreach($m as $y => $row){
- foreach($row as $x => $val){
+ foreach($m as $row){
+ foreach($row as $val){
if($val){
$count++;
}
}
}
- return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
+ return (abs(100 * $count / $size / $size - 50) / 5) * 10;
}
}
diff --git a/vendor/chillerlan/php-qrcode/src/Data/Number.php b/vendor/chillerlan/php-qrcode/src/Data/Number.php
index 3936d12..0a905b1 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/Number.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/Number.php
@@ -4,7 +4,7 @@
*
* @filesource Number.php
* @created 26.11.2015
- * @package QRCode
+ * @package chillerlan\QRCode\Data
* @author Smiley
* @copyright 2015 Smiley
* @license MIT
@@ -14,22 +14,19 @@
use chillerlan\QRCode\QRCode;
-use function ord, sprintf, substr;
+use function ord, sprintf, str_split, substr;
/**
- * Numeric mode: decimal digits 0 through 9
+ * Numeric mode: decimal digits 0 to 9
+ *
+ * ISO/IEC 18004:2000 Section 8.3.2
+ * ISO/IEC 18004:2000 Section 8.4.2
*/
-class Number extends QRDataAbstract{
+final class Number extends QRDataAbstract{
- /**
- * @inheritdoc
- */
- protected $datamode = QRCode::DATA_NUMBER;
+ protected int $datamode = QRCode::DATA_NUMBER;
- /**
- * @inheritdoc
- */
- protected $lengthBits = [10, 12, 14];
+ protected array $lengthBits = [10, 12, 14];
/**
* @inheritdoc
@@ -56,20 +53,18 @@ protected function write(string $data):void{
}
/**
- * @param string $string
+ * get the code for the given numeric string
*
- * @return int
- * @throws \chillerlan\QRCode\Data\QRCodeDataException
+ * @throws \chillerlan\QRCode\Data\QRCodeDataException on an illegal character occurence
*/
protected function parseInt(string $string):int{
$num = 0;
- $len = strlen($string);
- for($i = 0; $i < $len; $i++){
- $c = ord($string[$i]);
+ foreach(str_split($string) as $chr){
+ $c = ord($chr);
- if(!in_array($string[$i], $this::NUMBER_CHAR_MAP, true)){
- throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $string[$i], $c));
+ if(!isset($this::CHAR_MAP_NUMBER[$chr])){
+ throw new QRCodeDataException(sprintf('illegal char: "%s" [%d]', $chr, $c));
}
$c = $c - 48; // ord('0')
diff --git a/vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php b/vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php
index f52767e..72b67b7 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/QRDataAbstract.php
@@ -12,7 +12,7 @@
namespace chillerlan\QRCode\Data;
-use chillerlan\QRCode\{QRCode, QRCodeException};
+use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\Helpers\{BitBuffer, Polynomial};
use chillerlan\Settings\SettingsContainerInterface;
@@ -25,68 +25,50 @@ abstract class QRDataAbstract implements QRDataInterface{
/**
* the string byte count
- *
- * @var int
*/
- protected $strlen;
+ protected ?int $strlen = null;
/**
* the current data mode: Num, Alphanum, Kanji, Byte
- *
- * @var int
*/
- protected $datamode;
+ protected int $datamode;
/**
* mode length bits for the version breakpoints 1-9, 10-26 and 27-40
*
- * @var array
+ * ISO/IEC 18004:2000 Table 3 - Number of bits in Character Count Indicator
*/
- protected $lengthBits = [0, 0, 0];
+ protected array $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;
+ protected int $version;
/**
* ECC temp data
- *
- * @var array
*/
- protected $ecdata;
+ protected array $ecdata;
/**
* ECC temp data
- *
- * @var array
*/
- protected $dcdata;
+ protected array $dcdata;
/**
- * @var \chillerlan\QRCode\QROptions
+ * the options instance
+ *
+ * @var \chillerlan\Settings\SettingsContainerInterface|\chillerlan\QRCode\QROptions
*/
- protected $options;
+ protected SettingsContainerInterface $options;
/**
- * @var \chillerlan\QRCode\Helpers\BitBuffer
+ * a BitBuffer instance
*/
- protected $bitBuffer;
+ protected BitBuffer $bitBuffer;
/**
* QRDataInterface constructor.
- *
- * @param \chillerlan\Settings\SettingsContainerInterface $options
- * @param string|null $data
*/
public function __construct(SettingsContainerInterface $options, string $data = null){
$this->options = $options;
@@ -110,10 +92,7 @@ public function setData(string $data):QRDataInterface{
? $this->getMinimumVersion()
: $this->options->version;
- $this->matrixdata = $this
- ->writeBitBuffer($data)
- ->maskECC()
- ;
+ $this->writeBitBuffer($data);
return $this;
}
@@ -123,21 +102,14 @@ public function setData(string $data):QRDataInterface{
*/
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)
+ ->init($maskPattern, $test)
+ ->mapData($this->maskECC(), $maskPattern)
;
}
/**
* returns the length bits for the version breakpoints 1-9, 10-26 and 27-40
*
- * @return int
* @throws \chillerlan\QRCode\Data\QRCodeDataException
* @codeCoverageIgnore
*/
@@ -154,10 +126,6 @@ protected function getLengthBits():int{
/**
* returns the byte count of the $data string
- *
- * @param string $data
- *
- * @return int
*/
protected function getLength(string $data):int{
return strlen($data);
@@ -166,15 +134,17 @@ protected function getLength(string $data):int{
/**
* 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
+ $dataMode = QRCode::DATA_MODES[$this->datamode];
+ $eccMode = QRCode::ECC_MODES[$this->options->eccLevel];
+
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]];
+ $maxlength = $this::MAX_LENGTH[$version][$dataMode][$eccMode];
if($this->strlen <= $maxlength){
return $version;
@@ -188,81 +158,72 @@ protected function getMinimumVersion():int{
* 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
+ * @throws \chillerlan\QRCode\QRCodeException on data overflow
*/
- protected function writeBitBuffer(string $data):QRDataInterface{
+ protected function writeBitBuffer(string $data):void{
$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
+ // overflow, likely caused due to invalid version setting
+ if($this->bitBuffer->getLength() > $MAX_BITS){
+ throw new QRCodeDataException(sprintf('code length overflow. (%d > %d bit)', $this->bitBuffer->getLength(), $MAX_BITS));
}
- // end code.
- if($this->bitBuffer->length + 4 <= $MAX_BITS){
+ // add terminator (ISO/IEC 18004:2000 Table 2)
+ if($this->bitBuffer->getLength() + 4 <= $MAX_BITS){
$this->bitBuffer->put(0, 4);
}
// padding
- while($this->bitBuffer->length % 8 !== 0){
+ while($this->bitBuffer->getLength() % 8 !== 0){
$this->bitBuffer->putBit(false);
}
// padding
while(true){
- if($this->bitBuffer->length >= $MAX_BITS){
+ if($this->bitBuffer->getLength() >= $MAX_BITS){
break;
}
$this->bitBuffer->put(0xEC, 8);
- if($this->bitBuffer->length >= $MAX_BITS){
+ if($this->bitBuffer->getLength() >= $MAX_BITS){
break;
}
$this->bitBuffer->put(0x11, 8);
}
- return $this;
}
/**
* ECC masking
*
- * @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
+ * ISO/IEC 18004:2000 Section 8.5 ff
*
- * @return array
+ * @see http://www.thonky.com/qr-code-tutorial/error-correction-coding
*/
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->ecdata = array_fill(0, $rsCount, []);
$this->dcdata = $this->ecdata;
if($l2 > 0){
@@ -274,6 +235,8 @@ protected function maskECC():array{
$maxEcCount = 0;
$offset = 0;
+ $bitBuffer = $this->bitBuffer->getBuffer();
+
foreach($rsBlocks as $key => $block){
[$rsBlockTotal, $dcCount] = $block;
@@ -283,12 +246,12 @@ protected function maskECC():array{
$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];
+ $this->dcdata[$key][$a] = 0xff & $bitBuffer[$a + $offset];
}
[$num, $add] = $this->poly($key, $ecCount);
- foreach($this->ecdata[$key] as $c => $_z){
+ foreach($this->ecdata[$key] as $c => $_){
$modIndex = $c + $add;
$this->ecdata[$key][$c] = $modIndex >= 0 ? $num[$modIndex] : 0;
}
@@ -300,7 +263,7 @@ protected function maskECC():array{
$data = array_fill(0, $totalCodeCount, null);
$index = 0;
- $mask = function($arr, $count) use (&$data, &$index, $rsCount){
+ $mask = function(array $arr, int $count) use (&$data, &$index, $rsCount):void{
for($x = 0; $x < $count; $x++){
for($y = 0; $y < $rsCount; $y++){
if($x < count($arr[$y])){
@@ -318,10 +281,7 @@ protected function maskECC():array{
}
/**
- * @param int $key
- * @param int $count
- *
- * @return int[]
+ * helper method for the polynomial operations
*/
protected function poly(int $key, int $count):array{
$rsPoly = new Polynomial;
diff --git a/vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php b/vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php
index 6533862..c6cd923 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/QRDataInterface.php
@@ -13,25 +13,40 @@
namespace chillerlan\QRCode\Data;
/**
- *
+ * Specifies the methods reqired for the data modules (Number, Alphanum, Byte and Kanji)
+ * and holds version information in several constants
*/
interface QRDataInterface{
- const NUMBER_CHAR_MAP = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
+ /**
+ * @var int[]
+ */
+ public const CHAR_MAP_NUMBER = [
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 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', ' ', '$', '%', '*',
- '+', '-', '.', '/', ':',
+ /**
+ * ISO/IEC 18004:2000 Table 5
+ *
+ * @var int[]
+ */
+ public const CHAR_MAP_ALPHANUM = [
+ '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7,
+ '8' => 8, '9' => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15,
+ 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23,
+ 'O' => 24, 'P' => 25, 'Q' => 26, 'R' => 27, 'S' => 28, 'T' => 29, 'U' => 30, 'V' => 31,
+ 'W' => 32, 'X' => 33, 'Y' => 34, 'Z' => 35, ' ' => 36, '$' => 37, '%' => 38, '*' => 39,
+ '+' => 40, '-' => 41, '.' => 42, '/' => 43, ':' => 44,
];
/**
- * @link http://www.qrcode.com/en/about/version.html
+ * ISO/IEC 18004:2000 Tables 7-11 - Number of symbol characters and input data capacity for versions 1 to 40
+ *
+ * @see http://www.qrcode.com/en/about/version.html
+ *
+ * @var int [][][]
*/
- const MAX_LENGTH =[
+ public 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
@@ -75,7 +90,12 @@ interface QRDataInterface{
40 => [[7089, 5596, 3993, 3057], [4296, 3391, 2420, 1852], [2953, 2331, 1663, 1273], [1817, 1435, 1024, 784]], // 177
];
- const MAX_BITS = [
+ /**
+ * ISO/IEC 18004:2000 Tables 7-11 - Number of symbol characters and input data capacity for versions 1 to 40
+ *
+ * @var int [][]
+ */
+ public const MAX_BITS = [
// version => [L, M, Q, H ]
1 => [ 152, 128, 104, 72],
2 => [ 272, 224, 176, 128],
@@ -120,9 +140,11 @@ interface QRDataInterface{
];
/**
- * @link http://www.thonky.com/qr-code-tutorial/error-correction-table
+ * @see http://www.thonky.com/qr-code-tutorial/error-correction-table
+ *
+ * @var int [][][]
*/
- const RSBLOCKS = [
+ public 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]],
@@ -167,20 +189,11 @@ interface QRDataInterface{
/**
* 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;
diff --git a/vendor/chillerlan/php-qrcode/src/Data/QRMatrix.php b/vendor/chillerlan/php-qrcode/src/Data/QRMatrix.php
index a6d8b09..9212a60 100644
--- a/vendor/chillerlan/php-qrcode/src/Data/QRMatrix.php
+++ b/vendor/chillerlan/php-qrcode/src/Data/QRMatrix.php
@@ -18,29 +18,85 @@
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
+ * Holds a numerical representation of the final QR Code;
+ * maps the ECC coded binary data and applies the mask pattern
+ *
+ * @see 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;
+final class QRMatrix{
+
+ /*
+ * special values
+ */
+
+ /** @var int */
+ public const M_NULL = 0x00;
+ /** @var int */
+ public const M_LOGO = 0x14;
+ /** @var int */
+ public const M_LOGO_DARK = self::M_LOGO << 8;
+
+ /*
+ * light values
+ */
+
+ /** @var int */
+ public const M_DATA = 0x04;
+ /** @var int */
+ public const M_FINDER = 0x06;
+ /** @var int */
+ public const M_SEPARATOR = 0x08;
+ /** @var int */
+ public const M_ALIGNMENT = 0x0a;
+ /** @var int */
+ public const M_TIMING = 0x0c;
+ /** @var int */
+ public const M_FORMAT = 0x0e;
+ /** @var int */
+ public const M_VERSION = 0x10;
+ /** @var int */
+ public const M_QUIETZONE = 0x12;
+
+ /*
+ * dark values
+ */
+
+ /** @var int */
+ public const M_DARKMODULE = self::M_DARKMODULE_LIGHT << 8;
+ /** @var int */
+ public const M_DATA_DARK = self::M_DATA << 8;
+ /** @var int */
+ public const M_FINDER_DARK = self::M_FINDER << 8;
+ /** @var int */
+ public const M_ALIGNMENT_DARK = self::M_ALIGNMENT << 8;
+ /** @var int */
+ public const M_TIMING_DARK = self::M_TIMING << 8;
+ /** @var int */
+ public const M_FORMAT_DARK = self::M_FORMAT << 8;
+ /** @var int */
+ public const M_VERSION_DARK = self::M_VERSION << 8;
+ /** @var int */
+ public const M_FINDER_DOT = self::M_FINDER_DOT_LIGHT << 8;
+
+ /*
+ * values used for reversed reflectance
+ */
+
+ /** @var int */
+ public const M_DARKMODULE_LIGHT = 0x02;
+ /** @var int */
+ public const M_FINDER_DOT_LIGHT = 0x16;
+ /** @var int */
+ public const M_SEPARATOR_DARK = self::M_SEPARATOR << 8;
+ /** @var int */
+ public const M_QUIETZONE_DARK = self::M_QUIETZONE << 8;
/**
- * @link http://www.thonky.com/qr-code-tutorial/alignment-pattern-locations
+ * ISO/IEC 18004:2000 Annex E, Table E.1 - Row/column coordinates of center module of Alignment Patterns
+ *
+ * version -> pattern
*
- * version -> pattern
+ * @var int[][]
*/
protected const alignmentPattern = [
1 => [],
@@ -86,9 +142,11 @@ class QRMatrix{
];
/**
- * @link http://www.thonky.com/qr-code-tutorial/format-version-tables
+ * ISO/IEC 18004:2000 Annex D, Table D.1 - Version information bit stream for each version
*
* no version pattern for QR Codes < 7
+ *
+ * @var int[]
*/
protected const versionPattern = [
7 => 0b000111110010010100,
@@ -127,7 +185,13 @@ class QRMatrix{
40 => 0b101000110001101001,
];
- // ECC level -> mask pattern
+ /**
+ * ISO/IEC 18004:2000 Section 8.9 - Format Information
+ *
+ * ECC level -> mask pattern
+ *
+ * @var int[][]
+ */
protected const formatPattern = [
[ // L
0b111011111000100,
@@ -172,36 +236,35 @@ class QRMatrix{
];
/**
- * @var int
+ * the current QR Code version number
*/
- protected $version;
+ protected int $version;
/**
- * @var int
+ * the current ECC level
*/
- protected $eclevel;
+ protected int $eclevel;
/**
- * @var int
+ * the used mask pattern, set via QRMatrix::mapData()
*/
- protected $maskPattern = QRCode::MASK_PATTERN_AUTO;
+ protected int $maskPattern = QRCode::MASK_PATTERN_AUTO;
/**
- * @var int
+ * the size (side length) of the matrix
*/
- protected $moduleCount;
+ protected int $moduleCount;
/**
- * @var mixed[]
+ * the actual matrix data array
+ *
+ * @var int[][]
*/
- protected $matrix;
+ protected array $matrix;
/**
* QRMatrix constructor.
*
- * @param int $version
- * @param int $eclevel
- *
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function __construct(int $version, int $eclevel){
@@ -220,6 +283,21 @@ public function __construct(int $version, int $eclevel){
$this->matrix = array_fill(0, $this->moduleCount, array_fill(0, $this->moduleCount, $this::M_NULL));
}
+ /**
+ * shortcut to initialize the matrix
+ */
+ public function init(int $maskPattern, bool $test = null):QRMatrix{
+ return $this
+ ->setFinderPattern()
+ ->setSeparators()
+ ->setAlignmentPattern()
+ ->setTimingPattern()
+ ->setVersionNumber($test)
+ ->setFormatInfo($maskPattern, $test)
+ ->setDarkModule()
+ ;
+ }
+
/**
* Returns the data matrix, returns a pure boolean representation if $boolean is set to true
*
@@ -245,21 +323,21 @@ public function matrix(bool $boolean = false):array{
}
/**
- * @return int
+ * Returns the current version number
*/
public function version():int{
return $this->version;
}
/**
- * @return int
+ * Returns the current ECC level
*/
public function eccLevel():int{
return $this->eclevel;
}
/**
- * @return int
+ * Returns the current mask pattern
*/
public function maskPattern():int{
return $this->maskPattern;
@@ -269,8 +347,6 @@ public function maskPattern():int{
* 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;
@@ -278,11 +354,6 @@ public function size():int{
/**
* 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];
@@ -293,13 +364,6 @@ public function get(int $x, int $y):int{
*
* 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);
@@ -315,24 +379,17 @@ public function set(int $x, int $y, bool $value, int $M_TYPE):QRMatrix{
*
* 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;
+ 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);
+ $this->set(8, 4 * $this->version + 9, true, $this::M_DARKMODULE_LIGHT);
return $this;
}
@@ -340,14 +397,14 @@ public function setDarkModule():QRMatrix{
/**
* Draws the 7x7 finder patterns in the corners top left/right and bottom left
*
- * @return \chillerlan\QRCode\Data\QRMatrix
+ * ISO/IEC 18004:2000 Section 7.3.2
*/
public function setFinderPattern():QRMatrix{
$pos = [
[0, 0], // top left
- [$this->moduleCount - 7, 0], // bottom left
- [0, $this->moduleCount - 7], // top right
+ [$this->moduleCount - 7, 0], // top right
+ [0, $this->moduleCount - 7], // bottom left
];
foreach($pos as $c){
@@ -363,7 +420,7 @@ public function setFinderPattern():QRMatrix{
}
// 3*3 dot
else{
- $this->set($c[0] + $y, $c[1] + $x, true, $this::M_FINDER_DOT);
+ $this->set($c[0] + $y, $c[1] + $x, true, $this::M_FINDER_DOT_LIGHT);
}
}
}
@@ -375,7 +432,7 @@ public function setFinderPattern():QRMatrix{
/**
* Draws the separator lines around the finder patterns
*
- * @return \chillerlan\QRCode\Data\QRMatrix
+ * ISO/IEC 18004:2000 Section 7.3.3
*/
public function setSeparators():QRMatrix{
@@ -405,7 +462,7 @@ public function setSeparators():QRMatrix{
/**
* Draws the 5x5 alignment patterns
*
- * @return \chillerlan\QRCode\Data\QRMatrix
+ * ISO/IEC 18004:2000 Section 7.3.5
*/
public function setAlignmentPattern():QRMatrix{
@@ -435,7 +492,7 @@ public function setAlignmentPattern():QRMatrix{
/**
* Draws the timing pattern (h/v checkered line between the finder patterns)
*
- * @return \chillerlan\QRCode\Data\QRMatrix
+ * ISO/IEC 18004:2000 Section 7.3.4
*/
public function setTimingPattern():QRMatrix{
@@ -457,9 +514,7 @@ public function setTimingPattern():QRMatrix{
/**
* Draws the version information, 2x 3x6 pixel
*
- * @param bool|null $test
- *
- * @return \chillerlan\QRCode\Data\QRMatrix
+ * ISO/IEC 18004:2000 Section 8.10
*/
public function setVersionNumber(bool $test = null):QRMatrix{
$bits = $this::versionPattern[$this->version] ?? false;
@@ -483,10 +538,7 @@ public function setVersionNumber(bool $test = null):QRMatrix{
/**
* Draws the format info along the finder patterns
*
- * @param int $maskPattern
- * @param bool|null $test
- *
- * @return \chillerlan\QRCode\Data\QRMatrix
+ * ISO/IEC 18004:2000 Section 8.9
*/
public function setFormatInfo(int $maskPattern, bool $test = null):QRMatrix{
$bits = $this::formatPattern[QRCode::ECC_MODES[$this->eclevel]][$maskPattern] ?? 0;
@@ -524,9 +576,8 @@ public function setFormatInfo(int $maskPattern, bool $test = null):QRMatrix{
/**
* Draws the "quiet zone" of $size around the matrix
*
- * @param int|null $size
+ * ISO/IEC 18004:2000 Section 7.3.7
*
- * @return \chillerlan\QRCode\Data\QRMatrix
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function setQuietZone(int $size = null):QRMatrix{
@@ -574,27 +625,21 @@ public function setQuietZone(int $size = null):QRMatrix{
*
* @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){
+ if($this->eclevel !== QRCode::ECC_H){
throw new QRCodeDataException('ECC level "H" required to add logo space');
}
- // we need uneven sizes, adjust if needed
- if(($width % 2) === 0){
+ // we need uneven sizes to center the logo space, adjust if needed
+ if($startX === null && ($width % 2) === 0){
$width++;
}
- if(($height % 2) === 0){
+ if($startY === null && ($height % 2) === 0){
$height++;
}
@@ -618,8 +663,8 @@ public function setLogoSpace(int $width, int $height, int $startX = null, int $s
$startY = ($startY !== null ? $startY : ($length - $height) / 2) + $qz;
// clear the space
- foreach($this->matrix as $y => $row){
- foreach($row as $x => $val){
+ for($y = 0; $y < $this->moduleCount; $y++){
+ for($x = 0; $x < $this->moduleCount; $x++){
// out of bounds, skip
if($x < $start || $y < $start ||$x >= $end || $y >= $end){
continue;
@@ -635,7 +680,8 @@ public function setLogoSpace(int $width, int $height, int $startX = null, int $s
}
/**
- * Maps the binary $data array from QRDataInterface::maskECC() on the matrix, using $maskPattern
+ * Maps the binary $data array from QRDataInterface::maskECC() on the matrix,
+ * masking the data using $maskPattern (ISO/IEC 18004:2000 Section 8.8)
*
* @see \chillerlan\QRCode\Data\QRDataAbstract::maskECC()
*
@@ -647,10 +693,13 @@ public function setLogoSpace(int $width, int $height, int $startX = null, int $s
public function mapData(array $data, int $maskPattern):QRMatrix{
$this->maskPattern = $maskPattern;
$byteCount = count($data);
- $size = $this->moduleCount - 1;
+ $y = $this->moduleCount - 1;
+ $inc = -1;
+ $byteIndex = 0;
+ $bitIndex = 7;
$mask = $this->getMask($this->maskPattern);
- for($i = $size, $y = $size, $inc = -1, $byteIndex = 0, $bitIndex = 7; $i > 0; $i -= 2){
+ for($i = $y; $i > 0; $i -= 2){
if($i === 6){
$i--;
@@ -707,9 +756,6 @@ public function mapData(array $data, int $maskPattern):QRMatrix{
*
* @internal
*
- * @param int $maskPattern
- *
- * @return \Closure
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
protected function getMask(int $maskPattern):Closure{
@@ -719,14 +765,14 @@ protected function getMask(int $maskPattern):Closure{
}
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; },
+ 0b000 => fn($x, $y):int => ($x + $y) % 2,
+ 0b001 => fn($x, $y):int => $y % 2,
+ 0b010 => fn($x, $y):int => $x % 3,
+ 0b011 => fn($x, $y):int => ($x + $y) % 3,
+ 0b100 => fn($x, $y):int => ((int)($y / 2) + (int)($x / 3)) % 2,
+ 0b101 => fn($x, $y):int => (($x * $y) % 2) + (($x * $y) % 3),
+ 0b110 => fn($x, $y):int => ((($x * $y) % 2) + (($x * $y) % 3)) % 2,
+ 0b111 => fn($x, $y):int => ((($x * $y) % 3) + (($x + $y) % 2)) % 2,
][$maskPattern];
}
diff --git a/vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php b/vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php
index 0b4ff6a..de47f20 100644
--- a/vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php
+++ b/vendor/chillerlan/php-qrcode/src/Helpers/BitBuffer.php
@@ -14,20 +14,25 @@
use function count, floor;
-class BitBuffer{
+/**
+ * Holds the raw binary data
+ */
+final class BitBuffer{
/**
- * @var int[]
+ * The buffer content
+ *
+ * @var int[]
*/
- public $buffer = [];
+ protected array $buffer = [];
/**
- * @var int
+ * Length of the content (bits)
*/
- public $length = 0;
+ protected int $length = 0;
/**
- * @return \chillerlan\QRCode\Helpers\BitBuffer
+ * clears the buffer
*/
public function clear():BitBuffer{
$this->buffer = [];
@@ -37,10 +42,7 @@ public function clear():BitBuffer{
}
/**
- * @param int $num
- * @param int $length
- *
- * @return \chillerlan\QRCode\Helpers\BitBuffer
+ * appends a sequence of bits
*/
public function put(int $num, int $length):BitBuffer{
@@ -52,9 +54,7 @@ public function put(int $num, int $length):BitBuffer{
}
/**
- * @param bool $bit
- *
- * @return \chillerlan\QRCode\Helpers\BitBuffer
+ * appends a single bit
*/
public function putBit(bool $bit):BitBuffer{
$bufIndex = floor($this->length / 8);
@@ -72,4 +72,18 @@ public function putBit(bool $bit):BitBuffer{
return $this;
}
+ /**
+ * returns the current buffer length
+ */
+ public function getLength():int{
+ return $this->length;
+ }
+
+ /**
+ * returns the buffer content
+ */
+ public function getBuffer():array{
+ return $this->buffer;
+ }
+
}
diff --git a/vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php b/vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php
index abe11d0..1385422 100644
--- a/vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php
+++ b/vendor/chillerlan/php-qrcode/src/Helpers/Polynomial.php
@@ -17,12 +17,14 @@
use function array_fill, count, sprintf;
/**
- * @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
+ * Polynomial long division helpers
+ *
+ * @see http://www.thonky.com/qr-code-tutorial/error-correction-coding
*/
-class Polynomial{
+final class Polynomial{
/**
- * @link http://www.thonky.com/qr-code-tutorial/log-antilog-table
+ * @see 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],
@@ -60,29 +62,26 @@ class Polynomial{
];
/**
- * @var array
+ * @var int[]
*/
- protected $num = [];
+ protected array $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[] $num
* @param int|null $shift
*
* @return \chillerlan\QRCode\Helpers\Polynomial
@@ -105,7 +104,7 @@ public function setNum(array $num, int $shift = null):Polynomial{
}
/**
- * @param array $e
+ * @param int[] $e
*
* @return \chillerlan\QRCode\Helpers\Polynomial
*/
@@ -127,7 +126,7 @@ public function multiply(array $e):Polynomial{
}
/**
- * @param array $e
+ * @param int[] $e
*
* @return \chillerlan\QRCode\Helpers\Polynomial
*/
@@ -150,9 +149,6 @@ public function mod(array $e):Polynomial{
}
/**
- * @param int $n
- *
- * @return int
* @throws \chillerlan\QRCode\QRCodeException
*/
public function glog(int $n):int{
@@ -161,13 +157,11 @@ public function glog(int $n):int{
throw new QRCodeException(sprintf('log(%s)', $n));
}
- return Polynomial::table[$n][1];
+ return self::table[$n][1];
}
/**
- * @param int $n
*
- * @return int
*/
public function gexp(int $n):int{
@@ -178,7 +172,7 @@ public function gexp(int $n):int{
$n -= 255;
}
- return Polynomial::table[$n][0];
+ return self::table[$n][0];
}
}
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php b/vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php
index a706685..a15ae9f 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QRFpdf.php
@@ -69,7 +69,7 @@ protected function setModuleValues():void{
* @return string|\FPDF
*/
public function dump(string $file = null){
- $file = $file ?? $this->options->cachefile;
+ $file ??= $this->options->cachefile;
$fpdf = new FPDF('P', $this->options->fpdfMeasureUnit, [$this->length, $this->length]);
$fpdf->AddPage();
@@ -83,6 +83,7 @@ public function dump(string $file = null){
$color = $this->moduleValues[$M_TYPE];
if($prevColor === null || $prevColor !== $color){
+ /** @phan-suppress-next-line PhanParamTooFewUnpack */
$fpdf->SetFillColor(...$color);
$prevColor = $color;
}
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRImage.php b/vendor/chillerlan/php-qrcode/src/Output/QRImage.php
index 598948c..8f533d3 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QRImage.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QRImage.php
@@ -19,30 +19,36 @@
use chillerlan\Settings\SettingsContainerInterface;
use Exception;
-use function array_values, base64_encode, call_user_func, count, imagecolorallocate, imagecolortransparent,
+use function array_values, base64_encode, call_user_func, count, extension_loaded, 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
+ * Converts the matrix into GD images, raw or base64 output (requires ext-gd)
+ *
+ * @see http://php.net/manual/book.image.php
*/
class QRImage extends QROutputAbstract{
+ /**
+ * GD image types that support transparency
+ *
+ * @var string[]
+ */
protected const TRANSPARENCY_TYPES = [
QRCode::OUTPUT_IMAGE_PNG,
QRCode::OUTPUT_IMAGE_GIF,
];
- /**
- * @var string
- */
- protected $defaultMode = QRCode::OUTPUT_IMAGE_PNG;
+ protected string $defaultMode = QRCode::OUTPUT_IMAGE_PNG;
/**
+ * The GD image resource
+ *
* @see imagecreatetruecolor()
- * @var resource
+ * @var resource|\GdImage
+ *
+ * @phan-suppress PhanUndeclaredTypeProperty
*/
protected $image;
@@ -84,15 +90,20 @@ protected function setModuleValues():void{
/**
* @inheritDoc
*
- * @return string|resource
+ * @return string|resource|\GdImage
+ *
+ * @phan-suppress PhanUndeclaredTypeReturnType, PhanTypeMismatchReturn
*/
public function dump(string $file = null){
+ $file ??= $this->options->cachefile;
+
$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);
+ $tbg = $this->options->imageTransparencyBG;
+ /** @phan-suppress-next-line PhanParamTooFewInternalUnpack */
+ $background = imagecolorallocate($this->image, ...$tbg);
if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
imagecolortransparent($this->image, $background);
@@ -110,7 +121,11 @@ public function dump(string $file = null){
return $this->image;
}
- $imageData = $this->dumpImage($file);
+ $imageData = $this->dumpImage();
+
+ if($file !== null){
+ $this->saveToFile($imageData, $file);
+ }
if($this->options->imageBase64){
$imageData = sprintf('data:image/%s;base64,%s', $this->options->outputType, base64_encode($imageData));
@@ -120,11 +135,7 @@ public function dump(string $file = null){
}
/**
- * @param int $x
- * @param int $y
- * @param array $rgb
- *
- * @return void
+ * Creates a single QR pixel with the given settings
*/
protected function setPixel(int $x, int $y, array $rgb):void{
imagefilledrectangle(
@@ -133,20 +144,17 @@ protected function setPixel(int $x, int $y, array $rgb):void{
$y * $this->scale,
($x + 1) * $this->scale,
($y + 1) * $this->scale,
+ /** @phan-suppress-next-line PhanParamTooFewInternalUnpack */
imagecolorallocate($this->image, ...$rgb)
);
}
/**
- * @param string|null $file
+ * Creates the final image by calling the desired GD output function
*
- * @return string
-
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
- protected function dumpImage(string $file = null):string{
- $file = $file ?? $this->options->cachefile;
-
+ protected function dumpImage():string{
ob_start();
try{
@@ -164,14 +172,12 @@ protected function dumpImage(string $file = null):string{
ob_end_clean();
- if($file !== null){
- $this->saveToFile($imageData, $file);
- }
-
return $imageData;
}
/**
+ * PNG output
+ *
* @return void
*/
protected function png():void{
@@ -186,6 +192,7 @@ protected function png():void{
/**
* Jiff - like... JitHub!
+ *
* @return void
*/
protected function gif():void{
@@ -193,6 +200,8 @@ protected function gif():void{
}
/**
+ * JPG output
+ *
* @return void
*/
protected function jpg():void{
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRImagick.php b/vendor/chillerlan/php-qrcode/src/Output/QRImagick.php
index 03886cf..49516d3 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QRImagick.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QRImagick.php
@@ -19,24 +19,20 @@
use chillerlan\Settings\SettingsContainerInterface;
use Imagick, ImagickDraw, ImagickPixel;
-use function is_string;
+use function extension_loaded, is_string;
/**
- * ImageMagick output module
- * requires ext-imagick
- * @link http://php.net/manual/book.imagick.php
- * @link http://phpimagick.com
+ * ImageMagick output module (requires ext-imagick)
+ *
+ * @see http://php.net/manual/book.imagick.php
+ * @see http://phpimagick.com
*/
class QRImagick extends QROutputAbstract{
- /**
- * @var \Imagick
- */
- protected $imagick;
+ protected Imagick $imagick;
/**
* @inheritDoc
- * @throws \chillerlan\QRCode\QRCodeException
*/
public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
@@ -72,7 +68,7 @@ protected function setModuleValues():void{
* @return string|\Imagick
*/
public function dump(string $file = null){
- $file = $file ?? $this->options->cachefile;
+ $file ??= $this->options->cachefile;
$this->imagick = new Imagick;
$this->imagick->newImage(
@@ -98,7 +94,7 @@ public function dump(string $file = null){
}
/**
- * @return void
+ * Creates the QR image via ImagickDraw
*/
protected function drawImage():void{
$draw = new ImagickDraw;
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php b/vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php
index 15559da..53120ec 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QRMarkup.php
@@ -21,17 +21,13 @@
*/
class QRMarkup extends QROutputAbstract{
- /**
- * @var string
- */
- protected $defaultMode = QRCode::OUTPUT_MARKUP_SVG;
+ protected string $defaultMode = QRCode::OUTPUT_MARKUP_SVG;
/**
* @see \sprintf()
- *
- * @var string
*/
- protected $svgHeader = '';
+ protected string $svgHeader = '';
/**
* @inheritDoc
@@ -55,10 +51,15 @@ protected function setModuleValues():void{
}
/**
- * @return string
+ * HTML output
*/
- protected function html():string{
- $html = ''.$this->options->eol;
+ protected function html(string $file = null):string{
+
+ $html = empty($this->options->cssClass)
+ ? '
'
+ : '
';
+
+ $html .= $this->options->eol;
foreach($this->matrix->matrix() as $row){
$html .= '
';
@@ -72,19 +73,23 @@ protected function html():string{
$html .= '
'.$this->options->eol;
- if($this->options->cachefile){
- return '
'.$this->options->eol.$html.'';
+ if($file !== null){
+ /** @noinspection HtmlRequiredLangAttribute */
+ return sprintf(
+ '
QR Code %s',
+ $this->options->eol.$html
+ );
}
return $html;
}
/**
- * @link https://github.com/codemasher/php-qrcode/pull/5
+ * SVG output
*
- * @return string
+ * @see https://github.com/codemasher/php-qrcode/pull/5
*/
- protected function svg():string{
+ protected function svg(string $file = null):string{
$matrix = $this->matrix->matrix();
$svg = sprintf($this->svgHeader, $this->options->cssClass, $this->options->svgViewBoxSize ?? $this->moduleCount)
@@ -115,7 +120,9 @@ protected function svg():string{
}
if($count > 0){
- $len = $count;
+ $len = $count;
+ $start ??= 0; // avoid type coercion in sprintf() - phan happy
+
$path .= sprintf('M%s %s h%s v1 h-%sZ ', $start, $y, $len, $len);
// reset count
@@ -128,7 +135,10 @@ protected function svg():string{
}
if(!empty($path)){
- $svg .= sprintf('
', $M_TYPE, $this->options->cssClass, $value, $this->options->svgOpacity, $path);
+ $svg .= sprintf(
+ '
',
+ $M_TYPE, $this->options->cssClass, $value, $this->options->svgOpacity, $path
+ );
}
}
@@ -137,8 +147,9 @@ protected function svg():string{
$svg .= ''.$this->options->eol;
// if saving to file, append the correct headers
- if($this->options->cachefile){
- return ''.$this->options->eol.$svg;
+ if($file !== null){
+ return ''.
+ $this->options->eol.$svg;
}
if($this->options->imageBase64){
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php b/vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php
index 4ec47de..6165e1c 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QROutputAbstract.php
@@ -12,10 +12,11 @@
namespace chillerlan\QRCode\Output;
-use chillerlan\QRCode\{Data\QRMatrix, QRCode};
+use chillerlan\QRCode\QRCode;
+use chillerlan\QRCode\Data\QRMatrix;
use chillerlan\Settings\SettingsContainerInterface;
-use function call_user_func, dirname, file_put_contents, get_called_class, in_array, is_writable, sprintf;
+use function call_user_func_array, dirname, file_put_contents, get_called_class, in_array, is_writable, sprintf;
/**
* common output abstract
@@ -23,50 +24,53 @@
abstract class QROutputAbstract implements QROutputInterface{
/**
- * @var int
+ * the current size of the QR matrix
+ *
+ * @see \chillerlan\QRCode\Data\QRMatrix::size()
*/
- protected $moduleCount;
+ protected int $moduleCount;
/**
- * @param \chillerlan\QRCode\Data\QRMatrix $matrix
+ * the current output mode
+ *
+ * @see \chillerlan\QRCode\QROptions::$outputType
*/
- protected $matrix;
+ protected string $outputMode;
/**
- * @var \chillerlan\QRCode\QROptions
+ * the default output mode of the current output module
*/
- protected $options;
+ protected string $defaultMode;
/**
- * @var string
+ * the current scaling for a QR pixel
+ *
+ * @see \chillerlan\QRCode\QROptions::$scale
*/
- protected $outputMode;
+ protected int $scale;
/**
- * @var string;
+ * the side length of the QR image (modules * scale)
*/
- protected $defaultMode;
+ protected int $length;
/**
- * @var int
+ * an (optional) array of color values for the several QR matrix parts
*/
- protected $scale;
+ protected array $moduleValues;
/**
- * @var int
+ * the (filled) data matrix object
*/
- protected $length;
+ protected QRMatrix $matrix;
/**
- * @var array
+ * @var \chillerlan\Settings\SettingsContainerInterface|\chillerlan\QRCode\QROptions
*/
- protected $moduleValues;
+ protected SettingsContainerInterface $options;
/**
* QROutputAbstract constructor.
- *
- * @param \chillerlan\Settings\SettingsContainerInterface $options
- * @param \chillerlan\QRCode\Data\QRMatrix $matrix
*/
public function __construct(SettingsContainerInterface $options, QRMatrix $matrix){
$this->options = $options;
@@ -86,8 +90,6 @@ public function __construct(SettingsContainerInterface $options, QRMatrix $matri
/**
* Sets the initial module values (clean-up & defaults)
- *
- * @return void
*/
abstract protected function setModuleValues():void;
@@ -97,10 +99,6 @@ abstract protected function setModuleValues():void;
* @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{
@@ -116,9 +114,11 @@ protected function saveToFile(string $data, string $file):bool{
* @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;
+ $file ??= $this->options->cachefile;
+
+ // call the built-in output method with the optional file path as parameter
+ // to make the called method aware if a cache file was given
+ $data = call_user_func_array([$this, $this->outputMode ?? $this->defaultMode], [$file]);
if($file !== null){
$this->saveToFile($data, $file);
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php b/vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php
index d9149b0..b492c27 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QROutputInterface.php
@@ -19,35 +19,37 @@
*/
interface QROutputInterface{
- const DEFAULT_MODULE_VALUES = [
+ public 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
+ QRMatrix::M_NULL => false,
+ QRMatrix::M_DARKMODULE_LIGHT => false,
+ QRMatrix::M_DATA => false,
+ QRMatrix::M_FINDER => false,
+ QRMatrix::M_SEPARATOR => false,
+ QRMatrix::M_ALIGNMENT => false,
+ QRMatrix::M_TIMING => false,
+ QRMatrix::M_FORMAT => false,
+ QRMatrix::M_VERSION => false,
+ QRMatrix::M_QUIETZONE => false,
+ QRMatrix::M_LOGO => false,
+ QRMatrix::M_FINDER_DOT_LIGHT => false,
// 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
+ QRMatrix::M_DARKMODULE => true,
+ QRMatrix::M_DATA_DARK => true,
+ QRMatrix::M_FINDER_DARK => true,
+ QRMatrix::M_SEPARATOR_DARK => true,
+ QRMatrix::M_ALIGNMENT_DARK => true,
+ QRMatrix::M_TIMING_DARK => true,
+ QRMatrix::M_FORMAT_DARK => true,
+ QRMatrix::M_VERSION_DARK => true,
+ QRMatrix::M_QUIETZONE_DARK => true,
+ QRMatrix::M_LOGO_DARK => true,
+ QRMatrix::M_FINDER_DOT => true,
];
/**
* generates the output, optionally dumps it to a file, and returns it
*
- * @param string|null $file
- *
* @return mixed
*/
public function dump(string $file = null);
diff --git a/vendor/chillerlan/php-qrcode/src/Output/QRString.php b/vendor/chillerlan/php-qrcode/src/Output/QRString.php
index ba8d836..3ed5153 100644
--- a/vendor/chillerlan/php-qrcode/src/Output/QRString.php
+++ b/vendor/chillerlan/php-qrcode/src/Output/QRString.php
@@ -8,6 +8,9 @@
* @author Smiley
* @copyright 2015 Smiley
* @license MIT
+ *
+ * @noinspection PhpUnusedParameterInspection
+ * @noinspection PhpComposerExtensionStubsInspection
*/
namespace chillerlan\QRCode\Output;
@@ -21,10 +24,7 @@
*/
class QRString extends QROutputAbstract{
- /**
- * @var string
- */
- protected $defaultMode = QRCode::OUTPUT_STRING_TEXT;
+ protected string $defaultMode = QRCode::OUTPUT_STRING_TEXT;
/**
* @inheritDoc
@@ -48,9 +48,9 @@ protected function setModuleValues():void{
}
/**
- * @return string
+ * string output
*/
- protected function text():string{
+ protected function text(string $file = null):string{
$str = [];
foreach($this->matrix->matrix() as $row){
@@ -67,9 +67,9 @@ protected function text():string{
}
/**
- * @return string
+ * JSON output
*/
- protected function json():string{
+ protected function json(string $file = null):string{
return json_encode($this->matrix->matrix());
}
diff --git a/vendor/chillerlan/php-qrcode/src/QRCode.php b/vendor/chillerlan/php-qrcode/src/QRCode.php
index 91f7aa0..c45b8b5 100644
--- a/vendor/chillerlan/php-qrcode/src/QRCode.php
+++ b/vendor/chillerlan/php-qrcode/src/QRCode.php
@@ -13,51 +13,76 @@
namespace chillerlan\QRCode;
use chillerlan\QRCode\Data\{
- MaskPatternTester, QRCodeDataException, QRDataInterface, QRMatrix
+ AlphaNum, Byte, Kanji, MaskPatternTester, Number, QRCodeDataException, QRDataInterface, QRMatrix
};
use chillerlan\QRCode\Output\{
QRCodeOutputException, QRFpdf, QRImage, QRImagick, QRMarkup, QROutputInterface, QRString
};
use chillerlan\Settings\SettingsContainerInterface;
-use function array_search, call_user_func_array, class_exists, in_array, min, ord, strlen;
+use function call_user_func_array, class_exists, in_array, ord, strlen, strtolower, str_split;
/**
* Turns a text string into a Model 2 QR Code
*
- * @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
- * @link http://www.qrcode.com/en/codes/model12.html
- * @link http://www.thonky.com/qr-code-tutorial/
+ * @see https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
+ * @see http://www.qrcode.com/en/codes/model12.html
+ * @see https://www.swisseduc.ch/informatik/theoretische_informatik/qr_codes/docs/qr_standard.pdf
+ * @see https://en.wikipedia.org/wiki/QR_code
+ * @see http://www.thonky.com/qr-code-tutorial/
*/
class QRCode{
- /**
- * API constants
- */
- public const OUTPUT_MARKUP_HTML = 'html';
- public const OUTPUT_MARKUP_SVG = 'svg';
- public const OUTPUT_IMAGE_PNG = 'png';
- public const OUTPUT_IMAGE_JPG = 'jpg';
- public const OUTPUT_IMAGE_GIF = 'gif';
- public const OUTPUT_STRING_JSON = 'json';
- public const OUTPUT_STRING_TEXT = 'text';
- public const OUTPUT_IMAGICK = 'imagick';
- public const OUTPUT_FPDF = 'fpdf';
- public const OUTPUT_CUSTOM = 'custom';
-
+ /** @var int */
public const VERSION_AUTO = -1;
+ /** @var int */
public const MASK_PATTERN_AUTO = -1;
- public const ECC_L = 0b01; // 7%.
- public const ECC_M = 0b00; // 15%.
- public const ECC_Q = 0b11; // 25%.
- public const ECC_H = 0b10; // 30%.
+ // ISO/IEC 18004:2000 Table 2
+ /** @var int */
public const DATA_NUMBER = 0b0001;
+ /** @var int */
public const DATA_ALPHANUM = 0b0010;
+ /** @var int */
public const DATA_BYTE = 0b0100;
+ /** @var int */
public const DATA_KANJI = 0b1000;
+ /**
+ * References to the keys of the following tables:
+ *
+ * @see \chillerlan\QRCode\Data\QRDataInterface::MAX_LENGTH
+ *
+ * @var int[]
+ */
+ public const DATA_MODES = [
+ self::DATA_NUMBER => 0,
+ self::DATA_ALPHANUM => 1,
+ self::DATA_BYTE => 2,
+ self::DATA_KANJI => 3,
+ ];
+
+ // ISO/IEC 18004:2000 Tables 12, 25
+
+ /** @var int */
+ public const ECC_L = 0b01; // 7%.
+ /** @var int */
+ public const ECC_M = 0b00; // 15%.
+ /** @var int */
+ public const ECC_Q = 0b11; // 25%.
+ /** @var int */
+ public const ECC_H = 0b10; // 30%.
+
+ /**
+ * References to the keys of the following tables:
+ *
+ * @see \chillerlan\QRCode\Data\QRDataInterface::MAX_BITS
+ * @see \chillerlan\QRCode\Data\QRDataInterface::RSBLOCKS
+ * @see \chillerlan\QRCode\Data\QRMatrix::formatPattern
+ *
+ * @var int[]
+ */
public const ECC_MODES = [
self::ECC_L => 0,
self::ECC_M => 1,
@@ -65,49 +90,82 @@ class QRCode{
self::ECC_H => 3,
];
- public const DATA_MODES = [
- self::DATA_NUMBER => 0,
- self::DATA_ALPHANUM => 1,
- self::DATA_BYTE => 2,
- self::DATA_KANJI => 3,
- ];
+ /** @var string */
+ public const OUTPUT_MARKUP_HTML = 'html';
+ /** @var string */
+ public const OUTPUT_MARKUP_SVG = 'svg';
+ /** @var string */
+ public const OUTPUT_IMAGE_PNG = 'png';
+ /** @var string */
+ public const OUTPUT_IMAGE_JPG = 'jpg';
+ /** @var string */
+ public const OUTPUT_IMAGE_GIF = 'gif';
+ /** @var string */
+ public const OUTPUT_STRING_JSON = 'json';
+ /** @var string */
+ public const OUTPUT_STRING_TEXT = 'text';
+ /** @var string */
+ public const OUTPUT_IMAGICK = 'imagick';
+ /** @var string */
+ public const OUTPUT_FPDF = 'fpdf';
+ /** @var string */
+ public const OUTPUT_CUSTOM = 'custom';
+ /**
+ * Map of built-in output modules => capabilities
+ *
+ * @var string[][]
+ */
public const OUTPUT_MODES = [
- QRMarkup::class => [
+ QRMarkup::class => [
self::OUTPUT_MARKUP_SVG,
self::OUTPUT_MARKUP_HTML,
],
- QRImage::class => [
+ QRImage::class => [
self::OUTPUT_IMAGE_PNG,
self::OUTPUT_IMAGE_GIF,
self::OUTPUT_IMAGE_JPG,
],
- QRString::class => [
+ QRString::class => [
self::OUTPUT_STRING_JSON,
self::OUTPUT_STRING_TEXT,
],
QRImagick::class => [
self::OUTPUT_IMAGICK,
],
- QRFpdf::class => [
+ QRFpdf::class => [
self::OUTPUT_FPDF
]
];
/**
+ * Map of data mode => interface
+ *
+ * @var string[]
+ */
+ protected const DATA_INTERFACES = [
+ 'number' => Number::class,
+ 'alphanum' => AlphaNum::class,
+ 'kanji' => Kanji::class,
+ 'byte' => Byte::class,
+ ];
+
+ /**
+ * The settings container
+ *
* @var \chillerlan\QRCode\QROptions|\chillerlan\Settings\SettingsContainerInterface
*/
- protected $options;
+ protected SettingsContainerInterface $options;
/**
- * @var \chillerlan\QRCode\Data\QRDataInterface
+ * The selected data interface (Number, AlphaNum, Kanji, Byte)
*/
- protected $dataInterface;
+ protected QRDataInterface $dataInterface;
/**
* QRCode constructor.
*
- * @param \chillerlan\Settings\SettingsContainerInterface|null $options
+ * Sets the options instance, determines the current mb-encoding and sets it to UTF-8
*/
public function __construct(SettingsContainerInterface $options = null){
$this->options = $options ?? new QROptions;
@@ -116,9 +174,6 @@ public function __construct(SettingsContainerInterface $options = null){
/**
* Renders a QR Code for the given $data and QROptions
*
- * @param string $data
- * @param string|null $file
- *
* @return mixed
*/
public function render(string $data, string $file = null){
@@ -128,9 +183,6 @@ public function render(string $data, string $file = null){
/**
* Returns a QRMatrix object for the given $data and current QROptions
*
- * @param string $data
- *
- * @return \chillerlan\QRCode\Data\QRMatrix
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
public function getMatrix(string $data):QRMatrix{
@@ -142,7 +194,7 @@ public function getMatrix(string $data):QRMatrix{
$this->dataInterface = $this->initDataInterface($data);
$maskPattern = $this->options->maskPattern === $this::MASK_PATTERN_AUTO
- ? $this->getBestMaskPattern()
+ ? (new MaskPatternTester($this->dataInterface))->getBestMaskPattern()
: $this->options->maskPattern;
$matrix = $this->dataInterface->initMatrix($maskPattern);
@@ -154,49 +206,24 @@ public function getMatrix(string $data):QRMatrix{
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;
+ $interface = $this::DATA_INTERFACES[strtolower($this->options->dataModeOverride)] ?? null;
- return new $dataInterface($this->options, $data);
+ if($interface !== null){
+ return new $interface($this->options, $data);
}
- foreach($dataModes as $mode){
- $dataInterface = $dataNamespace.$mode;
+ foreach($this::DATA_INTERFACES as $mode => $dataInterface){
- if(call_user_func_array([$this, 'is'.$mode], [$data]) && class_exists($dataInterface)){
+ if(call_user_func_array([$this, 'is'.$mode], [$data])){
return new $dataInterface($this->options, $data);
}
@@ -208,14 +235,12 @@ public function initDataInterface(string $data):QRDataInterface{
/**
* returns a fresh (built-in) QROutputInterface
*
- * @param string $data
- *
- * @return \chillerlan\QRCode\Output\QROutputInterface
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
protected function initOutputInterface(string $data):QROutputInterface{
if($this->options->outputType === $this::OUTPUT_CUSTOM && class_exists($this->options->outputInterface)){
+ /** @phan-suppress-next-line PhanTypeExpectedObjectOrClassName */
return new $this->options->outputInterface($this->options, $this->getMatrix($data));
}
@@ -232,39 +257,25 @@ protected function initOutputInterface(string $data):QROutputInterface{
/**
* checks if a string qualifies as numeric
- *
- * @param string $string
- *
- * @return bool
*/
public function isNumber(string $string):bool{
- return $this->checkString($string, QRDataInterface::NUMBER_CHAR_MAP);
+ return $this->checkString($string, QRDataInterface::CHAR_MAP_NUMBER);
}
/**
* checks if a string qualifies as alphanumeric
- *
- * @param string $string
- *
- * @return bool
*/
public function isAlphaNum(string $string):bool{
- return $this->checkString($string, QRDataInterface::ALPHANUM_CHAR_MAP);
+ return $this->checkString($string, QRDataInterface::CHAR_MAP_ALPHANUM);
}
/**
* checks is a given $string matches the characters of a given $charmap, returns false on the first invalid occurence.
- *
- * @param string $string
- * @param array $charmap
- *
- * @return bool
*/
protected function checkString(string $string, array $charmap):bool{
- $len = strlen($string);
- for($i = 0; $i < $len; $i++){
- if(!in_array($string[$i], $charmap, true)){
+ foreach(str_split($string) as $chr){
+ if(!isset($charmap[$chr])){
return false;
}
}
@@ -274,10 +285,6 @@ protected function checkString(string $string, array $charmap):bool{
/**
* checks if a string qualifies as Kanji
- *
- * @param string $string
- *
- * @return bool
*/
public function isKanji(string $string):bool{
$i = 0;
@@ -298,13 +305,9 @@ public function isKanji(string $string):bool{
/**
* a dummy
- *
- * @param $data
- *
- * @return bool
*/
- protected function isByte(string $data):bool{
- return !empty($data);
+ public function isByte(string $data):bool{
+ return $data !== '';
}
}
diff --git a/vendor/chillerlan/php-qrcode/src/QRCodeException.php b/vendor/chillerlan/php-qrcode/src/QRCodeException.php
index 68af380..737a080 100644
--- a/vendor/chillerlan/php-qrcode/src/QRCodeException.php
+++ b/vendor/chillerlan/php-qrcode/src/QRCodeException.php
@@ -12,4 +12,9 @@
namespace chillerlan\QRCode;
-class QRCodeException extends \Exception{}
+use Exception;
+
+/**
+ * An exception container
+ */
+class QRCodeException extends Exception{}
diff --git a/vendor/chillerlan/php-qrcode/src/QROptions.php b/vendor/chillerlan/php-qrcode/src/QROptions.php
index 778ae04..e36f670 100644
--- a/vendor/chillerlan/php-qrcode/src/QROptions.php
+++ b/vendor/chillerlan/php-qrcode/src/QROptions.php
@@ -15,46 +15,39 @@
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
+ * The QRCode settings container
+ *
+ * @property int $version
+ * @property int $versionMin
+ * @property int $versionMax
+ * @property int $eccLevel
+ * @property int $maskPattern
+ * @property bool $addQuietzone
+ * @property int $quietzoneSize
+ * @property string|null $dataModeOverride
+ * @property string $outputType
+ * @property string|null $outputInterface
+ * @property string|null $cachefile
+ * @property string $eol
+ * @property int $scale
+ * @property string $cssClass
+ * @property float $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|null $imagickBG
+ * @property string $fpdfMeasureUnit
+ * @property array|null $moduleValues
*/
class QROptions extends SettingsContainerAbstract{
use QROptionsTrait;
diff --git a/vendor/chillerlan/php-qrcode/src/QROptionsTrait.php b/vendor/chillerlan/php-qrcode/src/QROptionsTrait.php
index 45d4cb4..13dfba1 100644
--- a/vendor/chillerlan/php-qrcode/src/QROptionsTrait.php
+++ b/vendor/chillerlan/php-qrcode/src/QROptionsTrait.php
@@ -8,146 +8,125 @@
* @author smiley
* @copyright 2018 smiley
* @license MIT
+ *
+ * @noinspection PhpUnused
*/
namespace chillerlan\QRCode;
-use function array_values, count, in_array, is_array, is_numeric, max, min, sprintf, strtolower;
+use function array_values, count, in_array, is_numeric, max, min, sprintf, strtolower;
+/**
+ * The QRCode plug-in settings & setter functionality
+ */
trait QROptionsTrait{
/**
* QR Code version number
*
- * [1 ... 40] or QRCode::VERSION_AUTO
- *
- * @var int
+ * [1 ... 40] or QRCode::VERSION_AUTO
*/
- protected $version = QRCode::VERSION_AUTO;
+ protected int $version = QRCode::VERSION_AUTO;
/**
- * Minimum QR version (if $version = QRCode::VERSION_AUTO)
+ * Minimum QR version
*
- * @var int
+ * if $version = QRCode::VERSION_AUTO
*/
- protected $versionMin = 1;
+ protected int $versionMin = 1;
/**
* Maximum QR version
- *
- * @var int
*/
- protected $versionMax = 40;
+ protected int $versionMax = 40;
/**
* Error correct level
*
- * QRCode::ECC_X where X is
- * L => 7%
- * M => 15%
- * Q => 25%
- * H => 30%
+ * QRCode::ECC_X where X is:
*
- * @var int
+ * - L => 7%
+ * - M => 15%
+ * - Q => 25%
+ * - H => 30%
*/
- protected $eccLevel = QRCode::ECC_L;
+ protected int $eccLevel = QRCode::ECC_L;
/**
* Mask Pattern to use
*
- * [0...7] or QRCode::MASK_PATTERN_AUTO
- *
- * @var int
+ * [0...7] or QRCode::MASK_PATTERN_AUTO
*/
- protected $maskPattern = QRCode::MASK_PATTERN_AUTO;
+ protected int $maskPattern = QRCode::MASK_PATTERN_AUTO;
/**
* Add a "quiet zone" (margin) according to the QR code spec
- *
- * @var bool
*/
- protected $addQuietzone = true;
+ protected bool $addQuietzone = true;
/**
* Size of the quiet zone
*
- * internally clamped to [0 ... $moduleCount / 2], defaults to 4 modules
- *
- * @var int
+ * internally clamped to [0 ... $moduleCount / 2], defaults to 4 modules
*/
- protected $quietzoneSize = 4;
+ protected int $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
+ * valid modes are: Number, AlphaNum, Kanji, Byte (case insensitive)
*
- * @var string|null
+ * @see https://github.com/chillerlan/php-qrcode/issues/39
+ * @see https://github.com/chillerlan/php-qrcode/issues/97 (changed default value to '')
*/
- protected $dataMode = null;
+ protected string $dataModeOverride = '';
/**
- * 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
+ * The output type
*
- * @var string
+ * - 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
*/
- protected $outputType = QRCode::OUTPUT_IMAGE_PNG;
+ protected string $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;
+ protected ?string $outputInterface = null;
/**
* /path/to/cache.file
- *
- * @var string|null
*/
- protected $cachefile = null;
+ protected ?string $cachefile = null;
/**
* newline string [HTML, SVG, TEXT]
- *
- * @var string
*/
- protected $eol = PHP_EOL;
+ protected string $eol = PHP_EOL;
/**
- * size of a QR code pixel [SVG, IMAGE_*]
- * HTML -> via CSS
- *
- * @var int
+ * size of a QR code pixel [SVG, IMAGE_*], HTML via CSS
*/
- protected $scale = 5;
+ protected int $scale = 5;
/**
* a common css class
- *
- * @var string
*/
- protected $cssClass = '';
+ protected string $cssClass = '';
/**
* SVG opacity
- *
- * @var float
*/
- protected $svgOpacity = 1.0;
+ protected float $svgOpacity = 1.0;
/**
* anything between
*
* @see https://developer.mozilla.org/docs/Web/SVG/Element/defs
- *
- * @var string
*/
- protected $svgDefs = '';
+ protected string $svgDefs = '';
/**
* SVG viewBox size. a single integer number which defines width/height of the viewBox attribute.
@@ -155,38 +134,28 @@ trait QROptionsTrait{
* viewBox="0 0 x x"
*
* @see https://css-tricks.com/scale-svg/#article-header-id-3
- *
- * @var int|null
*/
- protected $svgViewBoxSize = null;
+ protected ?int $svgViewBoxSize = null;
/**
* string substitute for dark
- *
- * @var string
*/
- protected $textDark = '🔴';
+ protected string $textDark = '██';
/**
* string substitute for light
- *
- * @var string
*/
- protected $textLight = '⭕';
+ protected string $textLight = '░░';
/**
* markup substitute for dark (CSS value)
- *
- * @var string
*/
- protected $markupDark = '#000';
+ protected string $markupDark = '#000';
/**
* markup substitute for light (CSS value)
- *
- * @var string
*/
- protected $markupLight = '#fff';
+ protected string $markupLight = '#fff';
/**
* Return the image resource instead of a render if applicable.
@@ -194,7 +163,7 @@ trait QROptionsTrait{
*
* Supported by the following modules:
*
- * - QRImage: resource
+ * - QRImage: resource (PHP < 8), GdImage
* - QRImagick: Imagick
* - QRFpdf: FPDF
*
@@ -202,85 +171,66 @@ trait QROptionsTrait{
*
* @var bool
*/
- protected $returnResource = false;
+ protected bool $returnResource = false;
/**
* toggle base64 or raw image data
- *
- * @var bool
*/
- protected $imageBase64 = true;
+ protected bool $imageBase64 = true;
/**
* toggle transparency, not supported by jpg
- *
- * @var bool
*/
- protected $imageTransparent = true;
+ protected bool $imageTransparent = true;
/**
* @see imagecolortransparent()
*
- * @var array [R, G, B]
+ * [R, G, B]
*/
- protected $imageTransparencyBG = [255, 255, 255];
+ protected array $imageTransparencyBG = [255, 255, 255];
/**
* @see imagepng()
- *
- * @var int
*/
- protected $pngCompression = -1;
+ protected int $pngCompression = -1;
/**
* @see imagejpeg()
- *
- * @var int
*/
- protected $jpegQuality = 85;
+ protected int $jpegQuality = 85;
/**
* Imagick output format
*
- * @see Imagick::setType()
- *
- * @var string
+ * @see \Imagick::setType()
*/
- protected $imagickFormat = 'png';
+ protected string $imagickFormat = 'png';
/**
* Imagick background color (defaults to "transparent")
*
* @see \ImagickPixel::__construct()
- *
- * @var string|null
*/
- protected $imagickBG = null;
+ protected ?string $imagickBG = null;
/**
* Measurement unit for FPDF output: pt, mm, cm, in (defaults to "pt")
*
* @see \FPDF::__construct()
*/
- protected $fpdfMeasureUnit = 'pt';
+ protected string $fpdfMeasureUnit = 'pt';
/**
* Module values map
*
- * HTML, IMAGICK: #ABCDEF, cssname, rgb(), rgba()...
- * IMAGE: [63, 127, 255] // R, G, B
- *
- * @var array|null
+ * - HTML, IMAGICK: #ABCDEF, cssname, rgb(), rgba()...
+ * - IMAGE: [63, 127, 255] // R, G, B
*/
- protected $moduleValues = null;
+ protected ?array $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));
@@ -292,10 +242,6 @@ protected function setMinMaxVersion(int $versionMin, int $versionMax):void{
/**
* sets the minimum version number
- *
- * @param int $version
- *
- * @return void
*/
protected function set_versionMin(int $version):void{
$this->setMinMaxVersion($version, $this->versionMax);
@@ -303,10 +249,6 @@ protected function set_versionMin(int $version):void{
/**
* sets the maximum version number
- *
- * @param int $version
- *
- * @return void
*/
protected function set_versionMax(int $version):void{
$this->setMinMaxVersion($this->versionMin, $version);
@@ -315,9 +257,6 @@ protected function set_versionMax(int $version):void{
/**
* sets the error correction level
*
- * @param int $eccLevel
- *
- * @return void
* @throws \chillerlan\QRCode\QRCodeException
*/
protected function set_eccLevel(int $eccLevel):void{
@@ -331,10 +270,6 @@ protected function set_eccLevel(int $eccLevel):void{
/**
* sets/clamps the mask pattern
- *
- * @param int $maskPattern
- *
- * @return void
*/
protected function set_maskPattern(int $maskPattern):void{
@@ -347,15 +282,12 @@ protected function set_maskPattern(int $maskPattern):void{
/**
* sets the transparency background color
*
- * @param mixed $imageTransparencyBG
- *
- * @return void
* @throws \chillerlan\QRCode\QRCodeException
*/
- protected function set_imageTransparencyBG($imageTransparencyBG):void{
+ protected function set_imageTransparencyBG(array $imageTransparencyBG):void{
// invalid value - set to white as default
- if(!is_array($imageTransparencyBG) || count($imageTransparencyBG) < 3){
+ if(count($imageTransparencyBG) < 3){
$this->imageTransparencyBG = [255, 255, 255];
return;
@@ -363,6 +295,11 @@ protected function set_imageTransparencyBG($imageTransparencyBG):void{
foreach($imageTransparencyBG as $k => $v){
+ // cut off exceeding items
+ if($k > 2){
+ break;
+ }
+
if(!is_numeric($v)){
throw new QRCodeException('Invalid RGB value.');
}
@@ -377,10 +314,6 @@ protected function set_imageTransparencyBG($imageTransparencyBG):void{
/**
* sets/clamps the version number
- *
- * @param int $version
- *
- * @return void
*/
protected function set_version(int $version):void{
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/AlphaNumTest.php b/vendor/chillerlan/php-qrcode/tests/Data/AlphaNumTest.php
deleted file mode 100644
index c29b1f6..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/AlphaNumTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\Data\{AlphaNum, QRCodeDataException};
-
-class AlphaNumTest extends DatainterfaceTestAbstract{
-
- protected $FQCN = AlphaNum::class;
- protected $testdata = '0 $%*+-./:';
- protected $expected = [
- 32, 80, 36, 212, 252, 15, 175, 251,
- 176, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 112, 43, 9, 248, 200, 194, 75, 25,
- 205, 173, 154, 68, 191, 16, 128,
- 92, 112, 20, 198, 27
- ];
-
- public function testGetCharCodeException(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('illegal char: "#" [35]');
-
- $this->dataInterface->setData('#');
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/ByteTest.php b/vendor/chillerlan/php-qrcode/tests/Data/ByteTest.php
deleted file mode 100644
index cbfe1fa..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/ByteTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\Data\Byte;
-
-class ByteTest extends DatainterfaceTestAbstract{
-
- protected $FQCN = Byte::class;
- protected $testdata = '[¯\_(ツ)_/¯]';
- protected $expected = [
- 64, 245, 188, 42, 245, 197, 242, 142,
- 56, 56, 66, 149, 242, 252, 42, 245,
- 208, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 79, 89, 226, 48, 209, 89, 151, 1,
- 12, 73, 42, 163, 11, 34, 255, 205,
- 21, 47, 250, 101
- ];
-
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/DatainterfaceTestAbstract.php b/vendor/chillerlan/php-qrcode/tests/Data/DatainterfaceTestAbstract.php
deleted file mode 100644
index 19d7461..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/DatainterfaceTestAbstract.php
+++ /dev/null
@@ -1,65 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\QROptions;
-use chillerlan\QRCode\Data\{QRCodeDataException, QRDataInterface, QRMatrix};
-use chillerlan\QRCodeTest\QRTestAbstract;
-
-abstract class DatainterfaceTestAbstract extends QRTestAbstract{
-
- /**
- * @var \chillerlan\QRCode\Data\QRDataAbstract
- */
- protected $dataInterface;
-
- protected $testdata;
- protected $expected;
-
- protected function setUp():void{
- parent::setUp();
-
- $this->dataInterface = $this->reflection->newInstanceArgs([new QROptions(['version' => 4])]);
- }
-
- public function testInstance(){
- $this->dataInterface = $this->reflection->newInstanceArgs([new QROptions, $this->testdata]);
-
- $this->assertInstanceOf(QRDataInterface::class, $this->dataInterface);
- }
-
- public function testSetData(){
- $this->dataInterface->setData($this->testdata);
-
- $this->assertSame($this->expected, $this->getProperty('matrixdata')->getValue($this->dataInterface));
- }
-
- public function testInitMatrix(){
- $m = $this->dataInterface->setData($this->testdata)->initMatrix(0);
-
- $this->assertInstanceOf(QRMatrix::class, $m);
- }
-
- public function testGetMinimumVersion(){
- $this->assertSame(1, $this->getMethod('getMinimumVersion')->invoke($this->dataInterface));
- }
-
- public function testGetMinimumVersionException(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('data exceeds');
-
- $this->getProperty('strlen')->setValue($this->dataInterface, 13370);
- $this->getMethod('getMinimumVersion')->invoke($this->dataInterface);
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/KanjiTest.php b/vendor/chillerlan/php-qrcode/tests/Data/KanjiTest.php
deleted file mode 100644
index 108b8fe..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/KanjiTest.php
+++ /dev/null
@@ -1,50 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\Data\{Kanji, QRCodeDataException};
-
-class KanjiTest extends DatainterfaceTestAbstract{
-
- protected $FQCN = Kanji::class;
- protected $testdata = '茗荷茗荷茗荷茗荷茗荷';
- protected $expected = [
- 128, 173, 85, 26, 95, 85, 70, 151,
- 213, 81, 165, 245, 84, 105, 125, 85,
- 26, 92, 0, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 195, 11, 221, 91, 141, 220, 163, 46,
- 165, 37, 163, 176, 79, 0, 64, 68,
- 96, 113, 54, 191
- ];
-
- public function testIllegalCharException1(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('illegal char at 1 [16191]');
-
- $this->dataInterface->setData('ÃÃ');
- }
-
- public function testIllegalCharException2(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('illegal char at 1');
-
- $this->dataInterface->setData('Ã');
- }
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/MaskPatternTesterTest.php b/vendor/chillerlan/php-qrcode/tests/Data/MaskPatternTesterTest.php
deleted file mode 100644
index ae4af9f..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/MaskPatternTesterTest.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\{QROptions, Data\Byte, Data\MaskPatternTester};
-use chillerlan\QRCodeTest\QRTestAbstract;
-
-class MaskPatternTesterTest extends QRTestAbstract{
-
- protected $FQCN = MaskPatternTester::class;
-
- // coverage
- public function testMaskpattern(){
- $matrix = (new Byte(new QROptions(['version' => 10]), 'test'))->initMatrix(3, true);
-
- $this->assertSame(4243, (new MaskPatternTester($matrix))->testPattern());
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/NumberTest.php b/vendor/chillerlan/php-qrcode/tests/Data/NumberTest.php
deleted file mode 100644
index 983346a..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/NumberTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\Data\{Number, QRCodeDataException};
-
-class NumberTest extends DatainterfaceTestAbstract{
-
- protected $FQCN = Number::class;
- protected $testdata = '0123456789';
- protected $expected = [
- 16, 40, 12, 86, 106, 105, 0, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 17, 236, 17, 236, 17, 236, 17, 236,
- 201, 141, 102, 116, 238, 162, 239, 230,
- 222, 37, 79, 192, 42, 109, 188, 72,
- 89, 63, 168, 151
- ];
-
- public function testGetCharCodeException(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('illegal char: "#" [35]');
-
- $this->dataInterface->setData('#');
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Data/QRMatrixTest.php b/vendor/chillerlan/php-qrcode/tests/Data/QRMatrixTest.php
deleted file mode 100644
index 531c82e..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Data/QRMatrixTest.php
+++ /dev/null
@@ -1,260 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Data;
-
-use chillerlan\QRCode\QRCode;
-use chillerlan\QRCode\QROptions;
-use chillerlan\QRCode\Data\{QRCodeDataException, QRMatrix};
-use chillerlan\QRCodeTest\QRTestAbstract;
-use ReflectionClass;
-
-class QRMatrixTest extends QRTestAbstract{
-
- protected $FQCN = QRMatrix::class;
-
- protected $version = 7;
-
- /**
- * @var \chillerlan\QRCode\Data\QRMatrix
- */
- protected $matrix;
-
- protected function setUp():void{
- parent::setUp();
-
- $this->matrix = $this->reflection->newInstanceArgs([$this->version, QRCode::ECC_L]);
- }
-
- public function testInvalidVersionException(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('invalid QR Code version');
-
- $this->reflection->newInstanceArgs([42, 0]);
- }
-
- public function testInvalidEccException(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('invalid ecc level');
-
- $this->reflection->newInstanceArgs([1, 42]);
- }
-
- public function testInstance(){
- $this->assertInstanceOf($this->FQCN, $this->matrix);
- }
-
- public function testSize(){
- $this->assertCount($this->matrix->size(), $this->matrix->matrix());
- }
-
- public function testVersion(){
- $this->assertSame($this->version, $this->matrix->version());
- }
-
- public function testECC(){
- $this->assertSame(QRCode::ECC_L, $this->matrix->eccLevel());
- }
-
- public function testMaskPattern(){
- $this->assertSame(-1, $this->matrix->maskPattern());
- }
-
- public function testGetSetCheck(){
- $this->matrix->set(10, 10, true, QRMatrix::M_TEST);
- $this->assertSame(65280, $this->matrix->get(10, 10));
- $this->assertTrue($this->matrix->check(10, 10));
-
- $this->matrix->set(20, 20, false, QRMatrix::M_TEST);
- $this->assertSame(255, $this->matrix->get(20, 20));
- $this->assertFalse($this->matrix->check(20, 20));
- }
-
- public function testSetDarkModule(){
- $this->matrix->setDarkModule();
-
- $this->assertSame(QRMatrix::M_DARKMODULE << 8, $this->matrix->get(8, $this->matrix->size() - 8));
- }
-
- public function testSetFinderPattern(){
- $this->matrix->setFinderPattern();
-
- $this->assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get(0, 0));
- $this->assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get(0, $this->matrix->size() - 1));
- $this->assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get($this->matrix->size() - 1, 0));
- }
-
- public function testSetSeparators(){
- $this->matrix->setSeparators();
-
- $this->assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get(7, 0));
- $this->assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get(0, 7));
- $this->assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get(0, $this->matrix->size() - 8));
- $this->assertSame(QRMatrix::M_SEPARATOR, $this->matrix->get($this->matrix->size() - 8, 0));
- }
-
- public function testSetAlignmentPattern(){
- $this->matrix
- ->setFinderPattern()
- ->setAlignmentPattern()
- ;
-
- $alignmentPattern = (new ReflectionClass(QRMatrix::class))->getConstant('alignmentPattern')[$this->version];
-
- foreach($alignmentPattern as $py){
- foreach($alignmentPattern as $px){
-
- if($this->matrix->get($px, $py) === QRMatrix::M_FINDER << 8){
- $this->assertSame(QRMatrix::M_FINDER << 8, $this->matrix->get($px, $py), 'skipped finder pattern');
- continue;
- }
-
- $this->assertSame(QRMatrix::M_ALIGNMENT << 8, $this->matrix->get($px, $py));
- }
- }
-
- }
-
- public function testSetTimingPattern(){
- $this->matrix
- ->setAlignmentPattern()
- ->setTimingPattern()
- ;
-
- $size = $this->matrix->size();
-
- for($i = 7; $i < $size - 7; $i++){
- if($i % 2 === 0){
- $p1 = $this->matrix->get(6, $i);
-
- if($p1 === QRMatrix::M_ALIGNMENT << 8){
- $this->assertSame(QRMatrix::M_ALIGNMENT << 8, $p1, 'skipped alignment pattern');
- continue;
- }
-
- $this->assertSame(QRMatrix::M_TIMING << 8, $p1);
- $this->assertSame(QRMatrix::M_TIMING << 8, $this->matrix->get($i, 6));
- }
- }
- }
-
- public function testSetVersionNumber(){
- $this->matrix->setVersionNumber(true);
-
- $this->assertSame(QRMatrix::M_VERSION, $this->matrix->get($this->matrix->size() - 9, 0));
- $this->assertSame(QRMatrix::M_VERSION, $this->matrix->get($this->matrix->size() - 11, 5));
- $this->assertSame(QRMatrix::M_VERSION, $this->matrix->get(0, $this->matrix->size() - 9));
- $this->assertSame(QRMatrix::M_VERSION, $this->matrix->get(5, $this->matrix->size() - 11));
- }
-
- public function testSetFormatInfo(){
- $this->matrix->setFormatInfo(0, true);
-
- $this->assertSame(QRMatrix::M_FORMAT, $this->matrix->get(8, 0));
- $this->assertSame(QRMatrix::M_FORMAT, $this->matrix->get(0, 8));
- $this->assertSame(QRMatrix::M_FORMAT, $this->matrix->get($this->matrix->size() - 1, 8));
- $this->assertSame(QRMatrix::M_FORMAT, $this->matrix->get($this->matrix->size() - 8, 8));
- }
-
- public function testSetQuietZone(){
- $size = $this->matrix->size();
- $q = 5;
-
- $this->matrix->set(0, 0, true, QRMatrix::M_TEST);
- $this->matrix->set($size - 1, $size - 1, true, QRMatrix::M_TEST);
-
- $this->matrix->setQuietZone($q);
-
- $this->assertCount($size + 2 * $q, $this->matrix->matrix());
- $this->assertCount($size + 2 * $q, $this->matrix->matrix()[$size - 1]);
-
- $size = $this->matrix->size();
- $this->assertSame(QRMatrix::M_QUIETZONE, $this->matrix->get(0, 0));
- $this->assertSame(QRMatrix::M_QUIETZONE, $this->matrix->get($size - 1, $size - 1));
-
- $this->assertSame(QRMatrix::M_TEST << 8, $this->matrix->get($q, $q));
- $this->assertSame(QRMatrix::M_TEST << 8, $this->matrix->get($size - 1 - $q, $size - 1 - $q));
- }
-
- public function testSetQuietZoneException(){
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('use only after writing data');
-
- $this->matrix->setQuietZone();
- }
-
- public function testSetLogoSpaceOrientation():void{
- $o = new QROptions;
- $o->version = 10;
- $o->eccLevel = QRCode::ECC_H;
- $o->addQuietzone = false;
-
- $matrix = (new QRCode($o))->getMatrix('testdata');
- // also testing size adjustment to uneven numbers
- $matrix->setLogoSpace(20, 14);
-
- // NW corner
- $this::assertNotSame(QRMatrix::M_LOGO, $matrix->get(17, 20));
- $this::assertSame(QRMatrix::M_LOGO, $matrix->get(18, 21));
-
- // SE corner
- $this::assertSame(QRMatrix::M_LOGO, $matrix->get(38, 35));
- $this::assertNotSame(QRMatrix::M_LOGO, $matrix->get(39, 36));
- }
-
- public function testSetLogoSpacePosition():void{
- $o = new QROptions;
- $o->version = 10;
- $o->eccLevel = QRCode::ECC_H;
- $o->addQuietzone = true;
- $o->quietzoneSize = 10;
-
- $m = (new QRCode($o))->getMatrix('testdata');
-
- // logo space should not overwrite quiet zone & function patterns
- $m->setLogoSpace(21, 21, -10, -10);
- $this::assertSame(QRMatrix::M_QUIETZONE, $m->get(9, 9));
- $this::assertSame(QRMatrix::M_FINDER << 8, $m->get(10, 10));
- $this::assertSame(QRMatrix::M_FINDER << 8, $m->get(16, 16));
- $this::assertSame(QRMatrix::M_SEPARATOR, $m->get(17, 17));
- $this::assertSame(QRMatrix::M_FORMAT << 8, $m->get(18, 18));
- $this::assertSame(QRMatrix::M_LOGO, $m->get(19, 19));
- $this::assertSame(QRMatrix::M_LOGO, $m->get(20, 20));
- $this::assertNotSame(QRMatrix::M_LOGO, $m->get(21, 21));
-
- // i just realized that setLogoSpace() could be called multiple times
- // on the same instance and i'm not going to do anything about it :P
- $m->setLogoSpace(21, 21, 45, 45);
- $this::assertNotSame(QRMatrix::M_LOGO, $m->get(54, 54));
- $this::assertSame(QRMatrix::M_LOGO, $m->get(55, 55));
- $this::assertSame(QRMatrix::M_QUIETZONE, $m->get(67, 67));
- }
-
- public function testSetLogoSpaceInvalidEccException():void{
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('ECC level "H" required to add logo space');
-
- (new QRCode)->getMatrix('testdata')->setLogoSpace(50, 50);
- }
-
- public function testSetLogoSpaceMaxSizeException():void{
- $this->expectException(QRCodeDataException::class);
- $this->expectExceptionMessage('logo space exceeds the maximum error correction capacity');
-
- $o = new QROptions;
- $o->version = 5;
- $o->eccLevel = QRCode::ECC_H;
-
- (new QRCode($o))->getMatrix('testdata')->setLogoSpace(50, 50);
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Helpers/BitBufferTest.php b/vendor/chillerlan/php-qrcode/tests/Helpers/BitBufferTest.php
deleted file mode 100644
index 25d1c35..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Helpers/BitBufferTest.php
+++ /dev/null
@@ -1,53 +0,0 @@
-
- * @copyright 2015 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Helpers;
-
-use chillerlan\QRCode\{QRCode, Helpers\BitBuffer};
-use chillerlan\QRCodeTest\QRTestAbstract;
-
-class BitBufferTest extends QRTestAbstract{
-
- /**
- * @var \chillerlan\QRCode\Helpers\BitBuffer
- */
- protected $bitBuffer;
-
- protected function setUp():void{
- $this->bitBuffer = new BitBuffer;
- }
-
- public function bitProvider(){
- return [
- 'number' => [QRCode::DATA_NUMBER, 16],
- 'alphanum' => [QRCode::DATA_ALPHANUM, 32],
- 'byte' => [QRCode::DATA_BYTE, 64],
- 'kanji' => [QRCode::DATA_KANJI, 128],
- ];
- }
-
- /**
- * @dataProvider bitProvider
- */
- public function testPut($data, $value){
- $this->bitBuffer->put($data, 4);
- $this->assertSame($value, $this->bitBuffer->buffer[0]);
- $this->assertSame(4, $this->bitBuffer->length);
- }
-
- public function testClear(){
- $this->bitBuffer->clear();
- $this->assertSame([], $this->bitBuffer->buffer);
- $this->assertSame(0, $this->bitBuffer->length);
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Helpers/PolynomialTest.php b/vendor/chillerlan/php-qrcode/tests/Helpers/PolynomialTest.php
deleted file mode 100644
index 7f6da30..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Helpers/PolynomialTest.php
+++ /dev/null
@@ -1,42 +0,0 @@
-
- * @copyright 2015 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Helpers;
-
-use chillerlan\QRCode\Helpers\Polynomial;
-use chillerlan\QRCode\QRCodeException;
-use chillerlan\QRCodeTest\QRTestAbstract;
-
-class PolynomialTest extends QRTestAbstract{
-
- /**
- * @var \chillerlan\QRCode\Helpers\Polynomial
- */
- protected $polynomial;
-
- protected function setUp():void{
- $this->polynomial = new Polynomial;
- }
-
- public function testGexp(){
- $this->assertSame(142, $this->polynomial->gexp(-1));
- $this->assertSame(133, $this->polynomial->gexp(128));
- $this->assertSame(2, $this->polynomial->gexp(256));
- }
-
- public function testGlogException(){
- $this->expectException(QRCodeException::class);
- $this->expectExceptionMessage('log(0)');
-
- $this->polynomial->glog(0);
- }
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Output/QRFpdfTest.php b/vendor/chillerlan/php-qrcode/tests/Output/QRFpdfTest.php
deleted file mode 100644
index 1b49182..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Output/QRFpdfTest.php
+++ /dev/null
@@ -1,83 +0,0 @@
-
- * @copyright 2020 smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Output;
-
-use FPDF;
-use chillerlan\QRCode\Output\{QRFpdf, QROutputInterface};
-use chillerlan\QRCode\{QRCode, QROptions};
-
-use function class_exists, substr;
-
-/**
- * Tests the QRFpdf output module
- */
-class QRFpdfTest extends QROutputTestAbstract{
-
- protected $FQCN = QRFpdf::class;
-
- /**
- * @inheritDoc
- * @internal
- */
- public function setUp():void{
-
- if(!class_exists(FPDF::class)){
- $this->markTestSkipped('FPDF not available');
- return;
- }
-
- parent::setUp();
- }
-
- /**
- * @inheritDoc
- */
- public function testSetModuleValues():void{
-
- $this->options->moduleValues = [
- // data
- 1024 => [0, 0, 0],
- 4 => [255, 255, 255],
- ];
-
- $this->outputInterface->dump();
-
- $this::assertTrue(true); // tricking the code coverage
- }
-
- /**
- * @inheritDoc
- */
- public function testRenderImage():void{
- $type = QRCode::OUTPUT_FPDF;
-
- $this->options->outputType = $type;
- $this->options->imageBase64 = false;
- $this->outputInterface->dump($this::cachefile.$type);
-
- // substr() to avoid CreationDate
- $expected = substr(file_get_contents($this::cachefile.$type), 0, 2000);
- $actual = substr($this->outputInterface->dump(), 0, 2000);
-
- $this::assertSame($expected, $actual);
- }
-
- public function testOutputGetResource():void{
- $this->options->returnResource = true;
-
- $this->setOutputInterface();
-
- $this::assertInstanceOf(FPDF::class, $this->outputInterface->dump());
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Output/QRImageTest.php b/vendor/chillerlan/php-qrcode/tests/Output/QRImageTest.php
deleted file mode 100644
index 34ecf4f..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Output/QRImageTest.php
+++ /dev/null
@@ -1,69 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Output;
-
-use chillerlan\QRCode\{QRCode, Output\QRImage};
-
-class QRImageTest extends QROutputTestAbstract{
-
- protected $FQCN = QRImage::class;
-
- public function types(){
- return [
- 'png' => [QRCode::OUTPUT_IMAGE_PNG],
- 'gif' => [QRCode::OUTPUT_IMAGE_GIF],
- 'jpg' => [QRCode::OUTPUT_IMAGE_JPG],
- ];
- }
-
- /**
- * @dataProvider types
- * @param $type
- */
- public function testImageOutput($type){
- $this->options->outputType = $type;
- $this->options->imageBase64 = false;
-
- $this->setOutputInterface();
- $this->outputInterface->dump($this::cachefile.$type);
- $img = $this->outputInterface->dump();
-
- if($type === QRCode::OUTPUT_IMAGE_JPG){ // jpeg encoding may cause different results
- $this->markAsRisky();
- }
-
- $this->assertSame($img, file_get_contents($this::cachefile.$type));
- }
-
- public function testSetModuleValues(){
-
- $this->options->moduleValues = [
- // data
- 1024 => [0, 0, 0],
- 4 => [255, 255, 255],
- ];
-
- $this->setOutputInterface()->dump();
-
- $this->assertTrue(true); // tricking the code coverage
- }
-
- public function testOutputGetResource():void{
- $this->options->returnResource = true;
-
- $this->setOutputInterface();
-
- $this::assertIsResource($this->outputInterface->dump());
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Output/QRImagickTest.php b/vendor/chillerlan/php-qrcode/tests/Output/QRImagickTest.php
deleted file mode 100644
index c927cc6..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Output/QRImagickTest.php
+++ /dev/null
@@ -1,66 +0,0 @@
-
- * @copyright 2018 smiley
- * @license MIT
- *
- * @noinspection PhpComposerExtensionStubsInspection
- */
-
-namespace chillerlan\QRCodeTest\Output;
-
-use Imagick;
-use chillerlan\QRCode\{QRCode, Output\QRImagick};
-
-class QRImagickTest extends QROutputTestAbstract{
-
- protected $FQCN = QRImagick::class;
-
- public function setUp():void{
-
- if(!extension_loaded('imagick')){
- $this->markTestSkipped('ext-imagick not loaded');
- return;
- }
-
- parent::setUp();
- }
-
- public function testImageOutput(){
- $type = QRCode::OUTPUT_IMAGICK;
-
- $this->options->outputType = $type;
- $this->setOutputInterface();
- $this->outputInterface->dump($this::cachefile.$type);
- $img = $this->outputInterface->dump();
-
- $this->assertSame($img, file_get_contents($this::cachefile.$type));
- }
-
- public function testSetModuleValues(){
-
- $this->options->moduleValues = [
- // data
- 1024 => '#4A6000',
- 4 => '#ECF9BE',
- ];
-
- $this->setOutputInterface()->dump();
-
- $this->assertTrue(true); // tricking the code coverage
- }
-
- public function testOutputGetResource():void{
- $this->options->returnResource = true;
-
- $this->setOutputInterface();
-
- $this::assertInstanceOf(Imagick::class, $this->outputInterface->dump());
- }
-
-}
diff --git a/vendor/chillerlan/php-qrcode/tests/Output/QRMarkupTest.php b/vendor/chillerlan/php-qrcode/tests/Output/QRMarkupTest.php
deleted file mode 100644
index 24fdc3c..0000000
--- a/vendor/chillerlan/php-qrcode/tests/Output/QRMarkupTest.php
+++ /dev/null
@@ -1,79 +0,0 @@
-
- * @copyright 2017 Smiley
- * @license MIT
- */
-
-namespace chillerlan\QRCodeTest\Output;
-
-use chillerlan\QRCode\{QRCode, Output\QRMarkup};
-
-class QRMarkupTest extends QROutputTestAbstract{
-
- protected $FQCN = QRMarkup::class;
-
- public function types(){
- return [
- 'html' => [QRCode::OUTPUT_MARKUP_HTML],
- 'svg' => [QRCode::OUTPUT_MARKUP_SVG],
- ];
- }
-
- /**
- * @dataProvider types
- * @param $type
- */
- public function testMarkupOutputFile($type){
- $this->options->outputType = $type;
- $this->options->cachefile = $this::cachefile.$type;
- $this->setOutputInterface();
- $data = $this->outputInterface->dump();
-
- $this->assertSame($data, file_get_contents($this->options->cachefile));
- }
-
- /**
- * @dataProvider types
- * @param $type
- */
- public function testMarkupOutput($type){
- $this->options->imageBase64 = false;
- $this->options->outputType = $type;
- $this->setOutputInterface();
-
- $expected = explode($this->options->eol, file_get_contents($this::cachefile.$type));
- // cut off the doctype & head
- array_shift($expected);
-
- if($type === QRCode::OUTPUT_MARKUP_HTML){
- // cut off the