+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"chillerlan/php-qrcode": "^5.0"
|
"chillerlan/php-qrcode": "^6.0.1"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|||||||
Generated
+68
-64
@@ -4,40 +4,44 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "b4f5229f78cd0eed0c7166614bf05110",
|
"content-hash": "c898c79e7e1cf9625a3a3f757c17ee0d",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "chillerlan/php-qrcode",
|
"name": "chillerlan/php-qrcode",
|
||||||
"version": "5.0.3",
|
"version": "6.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/chillerlan/php-qrcode.git",
|
"url": "https://github.com/chillerlan/php-qrcode.git",
|
||||||
"reference": "42e215640e9ebdd857570c9e4e52245d1ee51de2"
|
"reference": "49006e34bd5328f163e80329e7312f34dceea59b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/42e215640e9ebdd857570c9e4e52245d1ee51de2",
|
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/49006e34bd5328f163e80329e7312f34dceea59b",
|
||||||
"reference": "42e215640e9ebdd857570c9e4e52245d1ee51de2",
|
"reference": "49006e34bd5328f163e80329e7312f34dceea59b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"chillerlan/php-settings-container": "^2.1.6 || ^3.2.1",
|
"chillerlan/php-settings-container": "^3.2.1",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"php": "^7.4 || ^8.0"
|
"php": "^8.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"chillerlan/php-authenticator": "^4.3.1 || ^5.2.1",
|
"chillerlan/php-authenticator": "^5.3",
|
||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"phan/phan": "^5.4.5",
|
"intervention/image": "^3.11",
|
||||||
"phpcompatibility/php-compatibility": "10.x-dev",
|
"phan/phan": "^6.0.1",
|
||||||
|
"phpbench/phpbench": "^1.4",
|
||||||
"phpmd/phpmd": "^2.15",
|
"phpmd/phpmd": "^2.15",
|
||||||
"phpunit/phpunit": "^9.6",
|
"phpstan/phpstan": "^2.1.40",
|
||||||
"setasign/fpdf": "^1.8.2",
|
"phpstan/phpstan-deprecation-rules": "^2.0.4",
|
||||||
"slevomat/coding-standard": "^8.15",
|
"phpunit/phpunit": "^11.5",
|
||||||
"squizlabs/php_codesniffer": "^3.11"
|
"setasign/fpdf": "^1.8.6",
|
||||||
|
"slevomat/coding-standard": "^8.28",
|
||||||
|
"squizlabs/php_codesniffer": "^4.0"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
|
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
|
||||||
|
"intervention/image": "More advanced GD and ImageMagick output.",
|
||||||
"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"
|
"simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code"
|
||||||
},
|
},
|
||||||
@@ -75,7 +79,7 @@
|
|||||||
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
|
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "A QR Code generator and reader with a user-friendly API. PHP 7.4+",
|
"description": "A QR Code generator and reader with a user-friendly API. PHP 8.2+",
|
||||||
"homepage": "https://github.com/chillerlan/php-qrcode",
|
"homepage": "https://github.com/chillerlan/php-qrcode",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"phpqrcode",
|
"phpqrcode",
|
||||||
@@ -97,20 +101,20 @@
|
|||||||
"type": "Ko-Fi"
|
"type": "Ko-Fi"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-11-21T16:12:34+00:00"
|
"time": "2026-03-18T21:21:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "chillerlan/php-settings-container",
|
"name": "chillerlan/php-settings-container",
|
||||||
"version": "3.2.1",
|
"version": "3.3.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/chillerlan/php-settings-container.git",
|
"url": "https://github.com/chillerlan/php-settings-container.git",
|
||||||
"reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681"
|
"reference": "a0a487cbf5344f721eb504bf0f59bada40c381b7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
|
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/a0a487cbf5344f721eb504bf0f59bada40c381b7",
|
||||||
"reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
|
"reference": "a0a487cbf5344f721eb504bf0f59bada40c381b7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -118,11 +122,13 @@
|
|||||||
"php": "^8.1"
|
"php": "^8.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
"phan/phan": "^5.5.2",
|
||||||
"phpmd/phpmd": "^2.15",
|
"phpmd/phpmd": "^2.15",
|
||||||
"phpstan/phpstan": "^1.11",
|
"phpstan/phpstan": "^2.1.31",
|
||||||
"phpstan/phpstan-deprecation-rules": "^1.2",
|
"phpstan/phpstan-deprecation-rules": "^2.0.3",
|
||||||
"phpunit/phpunit": "^10.5",
|
"phpunit/phpunit": "^10.5",
|
||||||
"squizlabs/php_codesniffer": "^3.10"
|
"slevomat/coding-standard": "^8.22",
|
||||||
|
"squizlabs/php_codesniffer": "^4.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -147,7 +153,8 @@
|
|||||||
"Settings",
|
"Settings",
|
||||||
"configuration",
|
"configuration",
|
||||||
"container",
|
"container",
|
||||||
"helper"
|
"helper",
|
||||||
|
"property hook"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/chillerlan/php-settings-container/issues",
|
"issues": "https://github.com/chillerlan/php-settings-container/issues",
|
||||||
@@ -163,7 +170,7 @@
|
|||||||
"type": "ko_fi"
|
"type": "ko_fi"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-07-16T11:13:48+00:00"
|
"time": "2026-03-20T21:10:52+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
@@ -692,16 +699,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "amphp/process",
|
"name": "amphp/process",
|
||||||
"version": "v2.0.3",
|
"version": "v2.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/amphp/process.git",
|
"url": "https://github.com/amphp/process.git",
|
||||||
"reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d"
|
"reference": "583959df17d00304ad7b0b32285373f985935643"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d",
|
"url": "https://api.github.com/repos/amphp/process/zipball/583959df17d00304ad7b0b32285373f985935643",
|
||||||
"reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d",
|
"reference": "583959df17d00304ad7b0b32285373f985935643",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -715,7 +722,7 @@
|
|||||||
"amphp/php-cs-fixer-config": "^2",
|
"amphp/php-cs-fixer-config": "^2",
|
||||||
"amphp/phpunit-util": "^3",
|
"amphp/phpunit-util": "^3",
|
||||||
"phpunit/phpunit": "^9",
|
"phpunit/phpunit": "^9",
|
||||||
"psalm/phar": "^5.4"
|
"psalm/phar": "6.16.1"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -748,7 +755,7 @@
|
|||||||
"homepage": "https://amphp.org/process",
|
"homepage": "https://amphp.org/process",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/amphp/process/issues",
|
"issues": "https://github.com/amphp/process/issues",
|
||||||
"source": "https://github.com/amphp/process/tree/v2.0.3"
|
"source": "https://github.com/amphp/process/tree/v2.1.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -756,7 +763,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-04-19T03:13:44+00:00"
|
"time": "2026-05-31T15:11:55+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "amphp/serialization",
|
"name": "amphp/serialization",
|
||||||
@@ -986,28 +993,29 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/pcre",
|
"name": "composer/pcre",
|
||||||
"version": "3.3.2",
|
"version": "3.4.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/composer/pcre.git",
|
"url": "https://github.com/composer/pcre.git",
|
||||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
|
"reference": "d5a341b3fb61f3001970940afb1d332968a183ed"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
"url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed",
|
||||||
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
|
"reference": "d5a341b3fb61f3001970940afb1d332968a183ed",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.4 || ^8.0"
|
"php": "^7.4 || ^8.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"phpstan/phpstan": "<1.11.10"
|
"phpstan/phpstan": "<2.2.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpstan/phpstan": "^1.12 || ^2",
|
"phpstan/phpstan": "^2",
|
||||||
"phpstan/phpstan-strict-rules": "^1 || ^2",
|
"phpstan/phpstan-deprecation-rules": "^2",
|
||||||
"phpunit/phpunit": "^8 || ^9"
|
"phpstan/phpstan-strict-rules": "^2",
|
||||||
|
"phpunit/phpunit": "^9"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
@@ -1045,7 +1053,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/composer/pcre/issues",
|
"issues": "https://github.com/composer/pcre/issues",
|
||||||
"source": "https://github.com/composer/pcre/tree/3.3.2"
|
"source": "https://github.com/composer/pcre/tree/3.4.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1055,13 +1063,9 @@
|
|||||||
{
|
{
|
||||||
"url": "https://github.com/composer",
|
"url": "https://github.com/composer",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
|
|
||||||
"type": "tidelift"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-11-12T16:29:46+00:00"
|
"time": "2026-06-07T11:47:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "composer/semver",
|
"name": "composer/semver",
|
||||||
@@ -1567,16 +1571,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "johnpbloch/wordpress-core",
|
"name": "johnpbloch/wordpress-core",
|
||||||
"version": "6.9.0",
|
"version": "6.9.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/johnpbloch/wordpress-core.git",
|
"url": "https://github.com/johnpbloch/wordpress-core.git",
|
||||||
"reference": "4626d4e896c36ab77a69ce58627bc76243b5dd07"
|
"reference": "13e02e0047ca5c8ec8dc837c2de8a5bd3583b879"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/4626d4e896c36ab77a69ce58627bc76243b5dd07",
|
"url": "https://api.github.com/repos/johnpbloch/wordpress-core/zipball/13e02e0047ca5c8ec8dc837c2de8a5bd3583b879",
|
||||||
"reference": "4626d4e896c36ab77a69ce58627bc76243b5dd07",
|
"reference": "13e02e0047ca5c8ec8dc837c2de8a5bd3583b879",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1584,7 +1588,7 @@
|
|||||||
"php": ">=7.2.24"
|
"php": ">=7.2.24"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
"wordpress/core-implementation": "6.9.0"
|
"wordpress/core-implementation": "6.9.4"
|
||||||
},
|
},
|
||||||
"type": "wordpress-core",
|
"type": "wordpress-core",
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
@@ -1611,7 +1615,7 @@
|
|||||||
"source": "https://core.trac.wordpress.org/browser",
|
"source": "https://core.trac.wordpress.org/browser",
|
||||||
"wiki": "https://codex.wordpress.org/"
|
"wiki": "https://codex.wordpress.org/"
|
||||||
},
|
},
|
||||||
"time": "2025-12-02T19:10:58+00:00"
|
"time": "2026-03-11T15:27:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kelunik/certificate",
|
"name": "kelunik/certificate",
|
||||||
@@ -3246,16 +3250,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-mbstring",
|
"name": "symfony/polyfill-mbstring",
|
||||||
"version": "v1.38.1",
|
"version": "v1.38.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||||
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92"
|
"reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92",
|
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
|
||||||
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92",
|
"reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3307,7 +3311,7 @@
|
|||||||
"shim"
|
"shim"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1"
|
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3327,7 +3331,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-05-26T12:51:13+00:00"
|
"time": "2026-05-27T06:59:30+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-php84",
|
"name": "symfony/polyfill-php84",
|
||||||
@@ -3786,16 +3790,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "webmozart/assert",
|
"name": "webmozart/assert",
|
||||||
"version": "2.4.0",
|
"version": "2.4.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/webmozarts/assert.git",
|
"url": "https://github.com/webmozarts/assert.git",
|
||||||
"reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155"
|
"reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9007ea6f45ecf352a9422b36644e4bfc039b9155",
|
"url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70",
|
||||||
"reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155",
|
"reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -3846,9 +3850,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/webmozarts/assert/issues",
|
"issues": "https://github.com/webmozarts/assert/issues",
|
||||||
"source": "https://github.com/webmozarts/assert/tree/2.4.0"
|
"source": "https://github.com/webmozarts/assert/tree/2.4.1"
|
||||||
},
|
},
|
||||||
"time": "2026-05-20T13:07:01+00:00"
|
"time": "2026-06-15T15:31:57+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "wp-hooks/wordpress-core",
|
"name": "wp-hooks/wordpress-core",
|
||||||
|
|||||||
@@ -180,11 +180,18 @@ class RsvEmailListener {
|
|||||||
global $rsv_template_registry;
|
global $rsv_template_registry;
|
||||||
$engine = new RsvTemplateEngine(registry: $rsv_template_registry);
|
$engine = new RsvTemplateEngine(registry: $rsv_template_registry);
|
||||||
|
|
||||||
|
$form_definition = new RsvFormDefinition((string) $form_submit['form_id'], $definition['definition']);
|
||||||
|
$form_data = new RsvFormData($form_values);
|
||||||
|
|
||||||
|
// Calculated values (e.g. price) win over submitted fields so they can't be shadowed.
|
||||||
|
$symbols = array_merge($form_values, (new RsvFormCalculatedValues())->for($form_definition, $form_data));
|
||||||
|
|
||||||
// Subject is plain text: render without HTML-escaping, then strip tags/newlines.
|
// Subject is plain text: render without HTML-escaping, then strip tags/newlines.
|
||||||
$subject = sanitize_text_field($engine->render_plain($subject_tpl, $form_values));
|
$subject = sanitize_text_field($engine->render_plain($subject_tpl, $symbols));
|
||||||
|
|
||||||
// Body is HTML: the engine HTML-escapes all interpolated values.
|
// Body is HTML: the engine HTML-escapes all interpolated values.
|
||||||
$body = $engine->render($body_tpl, $form_values);
|
$body = $engine->render($body_tpl, $symbols);
|
||||||
|
error_log("Prc");
|
||||||
|
|
||||||
(new RsvEmailSender())->send($user_email, $subject, $body);
|
(new RsvEmailSender())->send($user_email, $subject, $body);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class RsvGoogleCalendarListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$calendar_id = self::resolve_calendar_id($gcal, $event->timetable_id);
|
$calendar_id = self::resolve_calendar_id($gcal, $event->reservation->timetable_id);
|
||||||
if (!$calendar_id) {
|
if (!$calendar_id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -24,8 +24,8 @@ class RsvGoogleCalendarListener {
|
|||||||
$gcal->add_event(
|
$gcal->add_event(
|
||||||
$calendar_id,
|
$calendar_id,
|
||||||
"Reservation #{$event->reservation->id}",
|
"Reservation #{$event->reservation->id}",
|
||||||
$event->reservation->start,
|
$event->reservation->start_utc,
|
||||||
$event->reservation->end,
|
$event->reservation->end_utc,
|
||||||
$event->reservation->user_email,
|
$event->reservation->user_email,
|
||||||
$event->reservation->id,
|
$event->reservation->id,
|
||||||
$status,
|
$status,
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class RsvTimetableRepository {
|
|||||||
'name' => $timetable->name,
|
'name' => $timetable->name,
|
||||||
'block_size' => $timetable->block_size,
|
'block_size' => $timetable->block_size,
|
||||||
'maintainer_email' => $timetable->maintainer_email,
|
'maintainer_email' => $timetable->maintainer_email,
|
||||||
|
'google_calendar_id' => $timetable->google_calendar_id,
|
||||||
],
|
],
|
||||||
['id' => $id]
|
['id' => $id]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/** Computes a form's total price as the sum of its elements' prices. */
|
||||||
|
class RsvFormPriceCalculator {
|
||||||
|
public function calculate(RsvFormDefinition $definition, RsvFormData $data): float {
|
||||||
|
global $rsv_form_price_registry;
|
||||||
|
|
||||||
|
$total = 0.0;
|
||||||
|
|
||||||
|
foreach ($definition->getElements() as $element) {
|
||||||
|
$calculator = $rsv_form_price_registry->get($element->getType());
|
||||||
|
if ($calculator === null) {
|
||||||
|
continue; // Unpriced element type contributes nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
$total += (float) $calculator($element, $data->getValue($element->getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class RsvFormPriceCalculatorRegistry {
|
||||||
|
/** @var array<string, callable(RsvFormElementDefinition, mixed): float> */
|
||||||
|
private array $calculators = [];
|
||||||
|
|
||||||
|
public function register(string $type, callable $calculator): void {
|
||||||
|
$this->calculators[$type] = $calculator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(string $type): ?callable {
|
||||||
|
return $this->calculators[$type] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Builds the registry and lets other modules contribute calculators. */
|
||||||
|
public static function boot(): self {
|
||||||
|
$registry = new self();
|
||||||
|
do_action('rsv-register-price-calculator', $registry);
|
||||||
|
return $registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/** Values derived from a submission (not entered by the visitor), exposed to templates. */
|
||||||
|
final class RsvFormCalculatedValues {
|
||||||
|
/** @return array<string, mixed> */
|
||||||
|
public function for(RsvFormDefinition $definition, RsvFormData $data): array {
|
||||||
|
return [
|
||||||
|
'price' => (new RsvFormPriceCalculator())->calculate($definition, $data),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The names these values expose, so template validation accepts {{ price }}.
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public static function names(): array {
|
||||||
|
return ['price'];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ final class RsvFormDefinitionValidator {
|
|||||||
* @return list<string>
|
* @return list<string>
|
||||||
*/
|
*/
|
||||||
private function symbols(array $elements): array {
|
private function symbols(array $elements): array {
|
||||||
$names = [];
|
$names = RsvFormCalculatedValues::names(); // calculated values are referencable too
|
||||||
foreach ($elements as $el) {
|
foreach ($elements as $el) {
|
||||||
$name = is_array($el) ? ($el['name'] ?? '') : '';
|
$name = is_array($el) ? ($el['name'] ?? '') : '';
|
||||||
if (is_string($name) && $name !== '') {
|
if (is_string($name) && $name !== '') {
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Reservair\Templating\Elements;
|
||||||
|
|
||||||
|
use Reservair\Templating\RsvTemplateElement;
|
||||||
|
use Reservair\Templating\RsvTemplateSymbols;
|
||||||
|
use chillerlan\QRCode\Output\QRGdImagePNG;
|
||||||
|
use chillerlan\QRCode\QRCode;
|
||||||
|
use chillerlan\QRCode\Data\QRMatrix;
|
||||||
|
use chillerlan\QRCode\QROptions;
|
||||||
|
use chillerlan\QRCode\Output\QROutputInterface;
|
||||||
|
|
||||||
|
/** Renders a QR payment code for the form's total price into an email body. */
|
||||||
|
class RsvQrPaymentElement implements RsvTemplateElement {
|
||||||
|
|
||||||
|
public function render(RsvTemplateSymbols $symbols): string {
|
||||||
|
$account = trim((string) $symbols->get('account', ''));
|
||||||
|
if ($account === '') {
|
||||||
|
return ''; // No payee account configured — nothing to render.
|
||||||
|
}
|
||||||
|
|
||||||
|
$payload = $this->spayd(
|
||||||
|
$account,
|
||||||
|
(float) $symbols->get('price', 0),
|
||||||
|
(string) $symbols->get('currency', 'CZK'),
|
||||||
|
(string) $symbols->get('message', ''),
|
||||||
|
(string) $symbols->get('variable_symbol', '')
|
||||||
|
);
|
||||||
|
|
||||||
|
$src = $this->image_url($payload);
|
||||||
|
if ($src === '') {
|
||||||
|
return ''; // Image could not be written.
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<img class="rsv-qr-payment" alt="' . esc_attr__('QR platba', 'reservair')
|
||||||
|
. '" src="' . esc_url($src) . '" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function symbols(): array {
|
||||||
|
return ['account', 'currency', 'message', 'variable_symbol'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Builds a SPAYD string (Czech QR payment). '*' is the field delimiter. */
|
||||||
|
private function spayd(string $account, float $price, string $currency, string $message, string $vs): string {
|
||||||
|
$parts = [
|
||||||
|
'SPD*1.0',
|
||||||
|
'ACC:' . $account,
|
||||||
|
'AM:' . number_format($price, 2, '.', ''),
|
||||||
|
'CC:' . $currency,
|
||||||
|
];
|
||||||
|
if ($message !== '') {
|
||||||
|
$parts[] = 'MSG:' . str_replace('*', ' ', $message);
|
||||||
|
}
|
||||||
|
if ($vs !== '') {
|
||||||
|
$parts[] = 'X-VS:' . preg_replace('/\D/', '', $vs);
|
||||||
|
}
|
||||||
|
return implode('*', $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the QR PNG under uploads (deduped by payload hash) and returns its
|
||||||
|
* public URL, or '' if it could not be written.
|
||||||
|
*/
|
||||||
|
private function image_url(string $payload): string {
|
||||||
|
$uploads = wp_upload_dir();
|
||||||
|
$dir = $uploads['basedir'] . '/reservair-qr';
|
||||||
|
$name = hash('sha256', $payload) . '.png';
|
||||||
|
$path = $dir . '/' . $name;
|
||||||
|
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
wp_mkdir_p($dir);
|
||||||
|
if (file_put_contents($path, $this->png($payload)) === false) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $uploads['baseurl'] . '/reservair-qr/' . $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function png(string $payload): string {
|
||||||
|
$options = new QROptions();
|
||||||
|
$options->version = 7;
|
||||||
|
$options->outputInterface = QRGdImagePNG::class;
|
||||||
|
$options->scale = 4;
|
||||||
|
$options->outputBase64 = false;
|
||||||
|
$options->bgColor = [200, 150, 200];
|
||||||
|
|
||||||
|
return (string) (new QRCode($options))->render($payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-1
@@ -3,6 +3,7 @@
|
|||||||
use Reservair\Templating\Elements\RsvReservationSummaryElement;
|
use Reservair\Templating\Elements\RsvReservationSummaryElement;
|
||||||
use Reservair\Templating\Elements\RsvReservationActionsElement;
|
use Reservair\Templating\Elements\RsvReservationActionsElement;
|
||||||
use Reservair\Templating\Elements\RsvResetFormButtonElement;
|
use Reservair\Templating\Elements\RsvResetFormButtonElement;
|
||||||
|
use Reservair\Templating\Elements\RsvQrPaymentElement;
|
||||||
/**
|
/**
|
||||||
* Plugin Name: Reservair
|
* Plugin Name: Reservair
|
||||||
* Description: A reservation and booking system for WordPress. Site visitors browse available time slots and submit reservation requests via a Gutenberg block; administrators manage timetables, services, forms, and reservations from the WordPress admin panel.
|
* Description: A reservation and booking system for WordPress. Site visitors browse available time slots and submit reservation requests via a Gutenberg block; administrators manage timetables, services, forms, and reservations from the WordPress admin panel.
|
||||||
@@ -33,7 +34,7 @@ register_activation_hook( __FILE__, [ 'RsvInstaller', 'install' ] );
|
|||||||
* plugins we might interact with) is fully loaded.
|
* plugins we might interact with) is fully loaded.
|
||||||
*/
|
*/
|
||||||
function rsv_bootstrap(): void {
|
function rsv_bootstrap(): void {
|
||||||
global $rsv_form_registry, $rsv_template_registry;
|
global $rsv_form_registry, $rsv_template_registry, $rsv_form_price_registry;
|
||||||
|
|
||||||
// Re-grant the custom capability after a plugin *update* (the activation hook
|
// Re-grant the custom capability after a plugin *update* (the activation hook
|
||||||
// only runs on activate). No-op once the stored version matches.
|
// only runs on activate). No-op once the stored version matches.
|
||||||
@@ -53,11 +54,26 @@ function rsv_bootstrap(): void {
|
|||||||
$rsv_form_registry->register( 'output-reservation-summary', new RsvReservationSummaryElementHandler() );
|
$rsv_form_registry->register( 'output-reservation-summary', new RsvReservationSummaryElementHandler() );
|
||||||
$rsv_form_registry->register( 'output-text', new RsvOutputTextElementHandler() );
|
$rsv_form_registry->register( 'output-text', new RsvOutputTextElementHandler() );
|
||||||
|
|
||||||
|
// Price calculators — extensions add per-element calculators via the action.
|
||||||
|
add_action( 'rsv-register-price-calculator', function ( RsvFormPriceCalculatorRegistry $reg ): void {
|
||||||
|
$reg->register( 'reservation', function ( RsvFormElementDefinition $def, $value ): float {
|
||||||
|
if ( ! is_array( $value ) || ! is_array( $value['timetable_reservations'] ?? null ) ) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$price_per_block = (float) $def->getAttr( 'price_per_block', 0 );
|
||||||
|
|
||||||
|
return $price_per_block * count( $value['timetable_reservations'] );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
$rsv_form_price_registry = RsvFormPriceCalculatorRegistry::boot();
|
||||||
|
|
||||||
// Template custom-element registry. Extensions register via the action.
|
// Template custom-element registry. Extensions register via the action.
|
||||||
add_action( 'rsv-template-register-custom-elements', function ( \Reservair\Templating\RsvTemplateRegistry $reg ): void {
|
add_action( 'rsv-template-register-custom-elements', function ( \Reservair\Templating\RsvTemplateRegistry $reg ): void {
|
||||||
$reg->register( 'reservation-summary', new RsvReservationSummaryElement() );
|
$reg->register( 'reservation-summary', new RsvReservationSummaryElement() );
|
||||||
$reg->register( 'reservation-actions', new RsvReservationActionsElement() );
|
$reg->register( 'reservation-actions', new RsvReservationActionsElement() );
|
||||||
$reg->register( 'reset-form-button', new RsvResetFormButtonElement() );
|
$reg->register( 'reset-form-button', new RsvResetFormButtonElement() );
|
||||||
|
$reg->register( 'qr-payment', new RsvQrPaymentElement() );
|
||||||
} );
|
} );
|
||||||
$rsv_template_registry = new \Reservair\Templating\RsvTemplateRegistry();
|
$rsv_template_registry = new \Reservair\Templating\RsvTemplateRegistry();
|
||||||
do_action( 'rsv-template-register-custom-elements', $rsv_template_registry );
|
do_action( 'rsv-template-register-custom-elements', $rsv_template_registry );
|
||||||
|
|||||||
Reference in New Issue
Block a user