diff --git a/.docker/symfony.conf b/.docker/symfony.conf index b5229bf6..0d69c00c 100644 --- a/.docker/symfony.conf +++ b/.docker/symfony.conf @@ -47,6 +47,7 @@ PassEnv PROVIDER_REICHELT_ENABLED PROVIDER_REICHELT_CURRENCY PROVIDER_REICHELT_COUNTRY PROVIDER_REICHELT_LANGUAGE PROVIDER_REICHELT_INCLUDE_VAT PassEnv PROVIDER_POLLIN_ENABLED PassEnv EDA_KICAD_CATEGORY_DEPTH + PassEnv SHOW_PART_IMAGE_OVERLAY # For most configuration files from conf-available/, which are # enabled or disabled at a global level, it is possible to diff --git a/.env b/.env index 19870ae9..a95b46fb 100644 --- a/.env +++ b/.env @@ -67,34 +67,6 @@ ERROR_PAGE_ADMIN_EMAIL='' # If this is set to true, solutions to common problems are shown on error pages. Disable this, if you do not want your users to see them... ERROR_PAGE_SHOW_HELP=1 -################################################################################## -# Info provider settings -################################################################################## - -# Digikey Provider: -# You can get your client id and secret from https://developer.digikey.com/ -PROVIDER_DIGIKEY_CLIENT_ID= -PROVIDER_DIGIKEY_SECRET= -# The currency to get prices in -PROVIDER_DIGIKEY_CURRENCY=EUR -# The language to get results in (en, de, fr, it, es, zh, ja, ko) -PROVIDER_DIGIKEY_LANGUAGE=en -# The country to get results for -PROVIDER_DIGIKEY_COUNTRY=DE - -# Octopart / Nexar Provider: -# You can get your API key from https://nexar.com/api -PROVIDER_OCTOPART_CLIENT_ID= -PROVIDER_OCTOPART_SECRET= -# The currency and country to get prices for (you have to set both to get meaningful results) -# 3 letter ISO currency code (e.g. EUR, USD, GBP) -PROVIDER_OCTOPART_CURRENCY=EUR -# 2 letter ISO country code (e.g. DE, US, GB) -PROVIDER_OCTOPART_COUNTRY=DE -# The number of results to get from Octopart while searching (please note that this counts towards your API limits) -PROVIDER_OCTOPART_SEARCH_LIMIT=10 -# Set to false to include non authorized offers in the results -PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS=1 ################################################################################## # EDA integration related settings @@ -157,9 +129,6 @@ NO_URL_REWRITE_AVAILABLE=0 # Set to 1, if Part-DB should redirect all HTTP requests to HTTPS. You dont need to configure this, if your webserver already does this. REDIRECT_TO_HTTPS=0 -# If you want to use fixer.io for currency conversion, you have to set this to your API key -FIXER_API_KEY=CHANGEME - # Override value if you want to show to show a given text on homepage. # When this is empty the content of config/banner.md is used as banner BANNER="" diff --git a/assets/controllers/pages/latex_preview_controller.js b/assets/controllers/pages/latex_preview_controller.js index 6113393a..7f1e611c 100644 --- a/assets/controllers/pages/latex_preview_controller.js +++ b/assets/controllers/pages/latex_preview_controller.js @@ -33,7 +33,10 @@ export default class extends Controller { { let value = ""; if (this.unitValue) { - value = "\\mathrm{" + this.inputTarget.value + "}"; + //Escape percentage signs + value = this.inputTarget.value.replace(/%/g, '\\%'); + + value = "\\mathrm{" + value + "}"; } else { value = this.inputTarget.value; } diff --git a/assets/controllers/pages/parameters_autocomplete_controller.js b/assets/controllers/pages/parameters_autocomplete_controller.js index cd82875a..e187aa42 100644 --- a/assets/controllers/pages/parameters_autocomplete_controller.js +++ b/assets/controllers/pages/parameters_autocomplete_controller.js @@ -85,7 +85,9 @@ export default class extends Controller tmp += '' + katex.renderToString(data.symbol) + '' } if (data.unit) { - tmp += '' + katex.renderToString('[' + data.unit + ']') + '' + let unit = data.unit.replace(/%/g, '\\%'); + unit = "\\mathrm{" + unit + "}"; + tmp += '' + katex.renderToString('[' + unit + ']') + '' } diff --git a/composer.json b/composer.json index 525075a7..50093e8a 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "hshn/base64-encoded-file": "^5.0", "jbtronics/2fa-webauthn": "^v2.2.0", "jbtronics/dompdf-font-loader-bundle": "^1.0.0", - "jbtronics/settings-bundle": "dev-master", + "jbtronics/settings-bundle": "^v2.6.0", "jfcherng/php-diff": "^6.14", "knpuniversity/oauth2-client-bundle": "^2.15", "league/csv": "^9.8.0", diff --git a/composer.lock b/composer.lock index b62b2e5f..c73a402c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "871a0310bf9b8201ee7c28c73c33691c", + "content-hash": "88e396c8b913ba47f157b58a248b0835", "packages": [ { "name": "amphp/amp", @@ -1657,16 +1657,16 @@ }, { "name": "doctrine/data-fixtures", - "version": "2.0.2", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "f7f1e12d6bceb58c204b3e77210a103c1c57601e" + "reference": "f65b353922b7ac48f360428e19b22fcce5aba134" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/f7f1e12d6bceb58c204b3e77210a103c1c57601e", - "reference": "f7f1e12d6bceb58c204b3e77210a103c1c57601e", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/f65b353922b7ac48f360428e19b22fcce5aba134", + "reference": "f65b353922b7ac48f360428e19b22fcce5aba134", "shasum": "" }, "require": { @@ -1680,14 +1680,14 @@ "doctrine/phpcr-odm": "<1.3.0" }, "require-dev": { - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^13", "doctrine/dbal": "^3.5 || ^4", "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", "doctrine/orm": "^2.14 || ^3", "ext-sqlite3": "*", "fig/log-test": "^1", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5.3", + "phpstan/phpstan": "2.1.17", + "phpunit/phpunit": "10.5.45", "symfony/cache": "^6.4 || ^7", "symfony/var-exporter": "^6.4 || ^7" }, @@ -1720,7 +1720,7 @@ ], "support": { "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/2.0.2" + "source": "https://github.com/doctrine/data-fixtures/tree/2.0.3" }, "funding": [ { @@ -1736,20 +1736,20 @@ "type": "tidelift" } ], - "time": "2025-01-21T13:21:31+00:00" + "time": "2025-06-27T19:59:58+00:00" }, { "name": "doctrine/dbal", - "version": "4.2.3", + "version": "4.2.4", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e" + "reference": "b37d160498ea91a2382a2ebe825c4ea6254fc0ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/33d2d7fe1269b2301640c44cf2896ea607b30e3e", - "reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/b37d160498ea91a2382a2ebe825c4ea6254fc0ec", + "reference": "b37d160498ea91a2382a2ebe825c4ea6254fc0ec", "shasum": "" }, "require": { @@ -1759,15 +1759,15 @@ "psr/log": "^1|^2|^3" }, "require-dev": { - "doctrine/coding-standard": "12.0.0", + "doctrine/coding-standard": "13.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.2", - "phpstan/phpstan": "2.1.1", - "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-phpunit": "2.0.6", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "10.5.39", - "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.10.2", + "phpunit/phpunit": "10.5.46", + "slevomat/coding-standard": "8.16.2", + "squizlabs/php_codesniffer": "3.13.1", "symfony/cache": "^6.3.8|^7.0", "symfony/console": "^5.4|^6.3|^7.0" }, @@ -1826,7 +1826,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.2.3" + "source": "https://github.com/doctrine/dbal/tree/4.2.4" }, "funding": [ { @@ -1842,7 +1842,7 @@ "type": "tidelift" } ], - "time": "2025-03-07T18:29:05+00:00" + "time": "2025-06-15T23:15:01+00:00" }, { "name": "doctrine/deprecations", @@ -1894,16 +1894,16 @@ }, { "name": "doctrine/doctrine-bundle", - "version": "2.14.1", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "0a118222ab21ba05bd9f17fbaa6a3800865274f4" + "reference": "d88294521a1bca943240adca65fa19ca8a7288c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/0a118222ab21ba05bd9f17fbaa6a3800865274f4", - "reference": "0a118222ab21ba05bd9f17fbaa6a3800865274f4", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/d88294521a1bca943240adca65fa19ca8a7288c6", + "reference": "d88294521a1bca943240adca65fa19ca8a7288c6", "shasum": "" }, "require": { @@ -1996,7 +1996,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.14.1" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.15.0" }, "funding": [ { @@ -2012,7 +2012,7 @@ "type": "tidelift" } ], - "time": "2025-06-09T20:22:28+00:00" + "time": "2025-06-16T19:53:58+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", @@ -2430,16 +2430,16 @@ }, { "name": "doctrine/migrations", - "version": "3.9.0", + "version": "3.9.1", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab" + "reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/325b61e41d032f5f7d7e2d11cbefff656eadc9ab", - "reference": "325b61e41d032f5f7d7e2d11cbefff656eadc9ab", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/0f1e0c960ac29866d648a4f50142a74fe1cb6999", + "reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999", "shasum": "" }, "require": { @@ -2513,7 +2513,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.9.0" + "source": "https://github.com/doctrine/migrations/tree/3.9.1" }, "funding": [ { @@ -2529,20 +2529,20 @@ "type": "tidelift" } ], - "time": "2025-03-26T06:48:45+00:00" + "time": "2025-06-27T07:19:23+00:00" }, { "name": "doctrine/orm", - "version": "3.4.0", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "4664373bd0668d71b40cc368b950de95e1dba2f8" + "reference": "6deec3655ba3e8f15280aac11e264225854d2369" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/4664373bd0668d71b40cc368b950de95e1dba2f8", - "reference": "4664373bd0668d71b40cc368b950de95e1dba2f8", + "url": "https://api.github.com/repos/doctrine/orm/zipball/6deec3655ba3e8f15280aac11e264225854d2369", + "reference": "6deec3655ba3e8f15280aac11e264225854d2369", "shasum": "" }, "require": { @@ -2617,9 +2617,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.4.0" + "source": "https://github.com/doctrine/orm/tree/3.5.0" }, - "time": "2025-06-14T11:47:14+00:00" + "time": "2025-07-01T17:40:53+00:00" }, { "name": "doctrine/persistence", @@ -3312,26 +3312,27 @@ }, { "name": "gregwar/captcha", - "version": "v1.2.1", + "version": "v1.3.0", "source": { "type": "git", "url": "https://github.com/Gregwar/Captcha.git", - "reference": "229d3cdfe33d6f1349e0aec94a26e9205a6db08e" + "reference": "4edbcd09fde4353b94ce550f43460eba73baf2cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Gregwar/Captcha/zipball/229d3cdfe33d6f1349e0aec94a26e9205a6db08e", - "reference": "229d3cdfe33d6f1349e0aec94a26e9205a6db08e", + "url": "https://api.github.com/repos/Gregwar/Captcha/zipball/4edbcd09fde4353b94ce550f43460eba73baf2cc", + "reference": "4edbcd09fde4353b94ce550f43460eba73baf2cc", "shasum": "" }, "require": { + "ext-fileinfo": "*", "ext-gd": "*", "ext-mbstring": "*", "php": ">=5.3.0", "symfony/finder": "*" }, "require-dev": { - "phpunit/phpunit": "^6.4" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6.4 || ^7.0 || ^8.0 || ^9.0" }, "type": "library", "autoload": { @@ -3363,22 +3364,22 @@ ], "support": { "issues": "https://github.com/Gregwar/Captcha/issues", - "source": "https://github.com/Gregwar/Captcha/tree/v1.2.1" + "source": "https://github.com/Gregwar/Captcha/tree/v1.3.0" }, - "time": "2023-09-26T13:45:37+00:00" + "time": "2025-06-23T12:25:54+00:00" }, { "name": "gregwar/captcha-bundle", - "version": "v2.3.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/Gregwar/CaptchaBundle.git", - "reference": "8eb95c0911a1db9e3b2f368f6319e0945b959a6c" + "reference": "090a3754f02cadb7ecdb531b090322dbe5c03c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Gregwar/CaptchaBundle/zipball/8eb95c0911a1db9e3b2f368f6319e0945b959a6c", - "reference": "8eb95c0911a1db9e3b2f368f6319e0945b959a6c", + "url": "https://api.github.com/repos/Gregwar/CaptchaBundle/zipball/090a3754f02cadb7ecdb531b090322dbe5c03c75", + "reference": "090a3754f02cadb7ecdb531b090322dbe5c03c75", "shasum": "" }, "require": { @@ -3398,7 +3399,7 @@ "type": "symfony-bundle", "autoload": { "psr-4": { - "Gregwar\\CaptchaBundle\\": "/" + "Gregwar\\CaptchaBundle\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -3430,9 +3431,9 @@ ], "support": { "issues": "https://github.com/Gregwar/CaptchaBundle/issues", - "source": "https://github.com/Gregwar/CaptchaBundle/tree/v2.3.0" + "source": "https://github.com/Gregwar/CaptchaBundle/tree/v2.4.0" }, - "time": "2024-06-06T13:14:57+00:00" + "time": "2025-06-24T10:25:23+00:00" }, { "name": "guzzlehttp/guzzle", @@ -3761,16 +3762,16 @@ }, { "name": "hshn/base64-encoded-file", - "version": "v5.0.1", + "version": "v5.0.2", "source": { "type": "git", "url": "https://github.com/hshn/base64-encoded-file.git", - "reference": "54fa81461ba4fbf5b67ed71d22b43ea5cc8c8748" + "reference": "49e38d27fcf01a2f5b142886d6ef20fa62132a2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hshn/base64-encoded-file/zipball/54fa81461ba4fbf5b67ed71d22b43ea5cc8c8748", - "reference": "54fa81461ba4fbf5b67ed71d22b43ea5cc8c8748", + "url": "https://api.github.com/repos/hshn/base64-encoded-file/zipball/49e38d27fcf01a2f5b142886d6ef20fa62132a2d", + "reference": "49e38d27fcf01a2f5b142886d6ef20fa62132a2d", "shasum": "" }, "require": { @@ -3817,9 +3818,9 @@ "description": "Provides handling base64 encoded files, and the integration of symfony/form", "support": { "issues": "https://github.com/hshn/base64-encoded-file/issues", - "source": "https://github.com/hshn/base64-encoded-file/tree/v5.0.1" + "source": "https://github.com/hshn/base64-encoded-file/tree/v5.0.2" }, - "time": "2023-12-24T07:23:07+00:00" + "time": "2025-07-06T05:52:34+00:00" }, { "name": "imagine/imagine", @@ -4000,7 +4001,7 @@ }, { "name": "jbtronics/settings-bundle", - "version": "dev-master", + "version": "v2.6.0", "source": { "type": "git", "url": "https://github.com/jbtronics/settings-bundle.git", @@ -4044,7 +4045,6 @@ "doctrine/doctrine-bundle": "To use the doctrine ORM storage", "symfony/twig-bridge": "Allows to access settings in twig templates" }, - "default-branch": true, "type": "symfony-bundle", "autoload": { "psr-4": { @@ -8358,16 +8358,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.21", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "d1abcf763a7414f2e572f676f22da7a06c8cd9ee" + "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/d1abcf763a7414f2e572f676f22da7a06c8cd9ee", - "reference": "d1abcf763a7414f2e572f676f22da7a06c8cd9ee", + "url": "https://api.github.com/repos/symfony/cache/zipball/c88690befb8d4a85dc321fb78d677507f5eb141b", + "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b", "shasum": "" }, "require": { @@ -8434,7 +8434,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.21" + "source": "https://github.com/symfony/cache/tree/v6.4.23" }, "funding": [ { @@ -8450,7 +8450,7 @@ "type": "tidelift" } ], - "time": "2025-04-08T08:21:20+00:00" + "time": "2025-06-27T18:31:36+00:00" }, { "name": "symfony/cache-contracts", @@ -8679,16 +8679,16 @@ }, { "name": "symfony/console", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3" + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", - "reference": "7d29659bc3c9d8e9a34e2c3414ef9e9e003e6cf3", + "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93", + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93", "shasum": "" }, "require": { @@ -8753,7 +8753,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.22" + "source": "https://github.com/symfony/console/tree/v6.4.23" }, "funding": [ { @@ -8769,7 +8769,7 @@ "type": "tidelift" } ], - "time": "2025-05-07T07:05:04+00:00" + "time": "2025-06-27T19:37:22+00:00" }, { "name": "symfony/css-selector", @@ -8838,16 +8838,16 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9" + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9", - "reference": "8cb11f833d1f5bfbb2df97dfc23c92b4d42c18d9", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0d9f24f3de0a83573fce5c9ed025d6306c6e166b", + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b", "shasum": "" }, "require": { @@ -8899,7 +8899,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.22" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.23" }, "funding": [ { @@ -8915,7 +8915,7 @@ "type": "tidelift" } ], - "time": "2025-05-17T07:35:26+00:00" + "time": "2025-06-23T06:49:06+00:00" }, { "name": "symfony/deprecation-contracts", @@ -8986,16 +8986,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "b880cebd0689a466cc4afef30009a54162c003c4" + "reference": "ef360932b8b342c0360b768b97776a12d5242db6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/b880cebd0689a466cc4afef30009a54162c003c4", - "reference": "b880cebd0689a466cc4afef30009a54162c003c4", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/ef360932b8b342c0360b768b97776a12d5242db6", + "reference": "ef360932b8b342c0360b768b97776a12d5242db6", "shasum": "" }, "require": { @@ -9074,7 +9074,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.22" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.23" }, "funding": [ { @@ -9090,20 +9090,20 @@ "type": "tidelift" } ], - "time": "2025-05-09T14:04:38+00:00" + "time": "2025-06-26T11:46:10+00:00" }, { "name": "symfony/dom-crawler", - "version": "v6.4.19", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "19073e3e0bb50cbc1cb286077069b3107085206f" + "reference": "22210aacb35dbadd772325d759d17bce2374a84d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/19073e3e0bb50cbc1cb286077069b3107085206f", - "reference": "19073e3e0bb50cbc1cb286077069b3107085206f", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/22210aacb35dbadd772325d759d17bce2374a84d", + "reference": "22210aacb35dbadd772325d759d17bce2374a84d", "shasum": "" }, "require": { @@ -9141,7 +9141,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.19" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.23" }, "funding": [ { @@ -9157,7 +9157,7 @@ "type": "tidelift" } ], - "time": "2025-02-14T17:58:34+00:00" + "time": "2025-06-13T12:10:00+00:00" }, { "name": "symfony/dotenv", @@ -9235,16 +9235,16 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "ce765a2d28b3cce61de1fb916e207767a73171d1" + "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/ce765a2d28b3cce61de1fb916e207767a73171d1", - "reference": "ce765a2d28b3cce61de1fb916e207767a73171d1", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/b088e0b175c30b4e06d8085200fa465b586f44fa", + "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa", "shasum": "" }, "require": { @@ -9290,7 +9290,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.22" + "source": "https://github.com/symfony/error-handler/tree/v6.4.23" }, "funding": [ { @@ -9306,7 +9306,7 @@ "type": "tidelift" } ], - "time": "2025-05-28T12:00:15+00:00" + "time": "2025-06-13T07:39:48+00:00" }, { "name": "symfony/event-dispatcher", @@ -9660,16 +9660,16 @@ }, { "name": "symfony/flex", - "version": "v2.7.1", + "version": "v2.8.1", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "4ae50d368415a06820739e54d38a4a29d6df9155" + "reference": "423c36e369361003dc31ef11c5f15fb589e52c01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/4ae50d368415a06820739e54d38a4a29d6df9155", - "reference": "4ae50d368415a06820739e54d38a4a29d6df9155", + "url": "https://api.github.com/repos/symfony/flex/zipball/423c36e369361003dc31ef11c5f15fb589e52c01", + "reference": "423c36e369361003dc31ef11c5f15fb589e52c01", "shasum": "" }, "require": { @@ -9708,7 +9708,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.7.1" + "source": "https://github.com/symfony/flex/tree/v2.8.1" }, "funding": [ { @@ -9724,20 +9724,20 @@ "type": "tidelift" } ], - "time": "2025-05-28T14:22:54+00:00" + "time": "2025-07-05T07:45:19+00:00" }, { "name": "symfony/form", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "2e2e32b7cc9e543a3f739b4968611a44ef17a2de" + "reference": "6f60a2a9031c49fe92b8703764defa46481db155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/2e2e32b7cc9e543a3f739b4968611a44ef17a2de", - "reference": "2e2e32b7cc9e543a3f739b4968611a44ef17a2de", + "url": "https://api.github.com/repos/symfony/form/zipball/6f60a2a9031c49fe92b8703764defa46481db155", + "reference": "6f60a2a9031c49fe92b8703764defa46481db155", "shasum": "" }, "require": { @@ -9805,7 +9805,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v6.4.22" + "source": "https://github.com/symfony/form/tree/v6.4.23" }, "funding": [ { @@ -9821,20 +9821,20 @@ "type": "tidelift" } ], - "time": "2025-05-04T06:52:29+00:00" + "time": "2025-06-05T16:22:31+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "b1de19b2083484d0ce945977f6c6484e9e493a2e" + "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b1de19b2083484d0ce945977f6c6484e9e493a2e", - "reference": "b1de19b2083484d0ce945977f6c6484e9e493a2e", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ff892d3ab4b8aa35921bc2120a4b31d57948fe22", + "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22", "shasum": "" }, "require": { @@ -9954,7 +9954,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.22" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.23" }, "funding": [ { @@ -9970,20 +9970,20 @@ "type": "tidelift" } ], - "time": "2025-05-14T07:14:36+00:00" + "time": "2025-06-26T21:24:02+00:00" }, { "name": "symfony/http-client", - "version": "v6.4.19", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "3294a433fc9d12ae58128174896b5b1822c28dad" + "reference": "19f11e742b94dcfd968a54f5381bb9082a88cb57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/3294a433fc9d12ae58128174896b5b1822c28dad", - "reference": "3294a433fc9d12ae58128174896b5b1822c28dad", + "url": "https://api.github.com/repos/symfony/http-client/zipball/19f11e742b94dcfd968a54f5381bb9082a88cb57", + "reference": "19f11e742b94dcfd968a54f5381bb9082a88cb57", "shasum": "" }, "require": { @@ -10047,7 +10047,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.19" + "source": "https://github.com/symfony/http-client/tree/v6.4.23" }, "funding": [ { @@ -10063,7 +10063,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T09:55:13+00:00" + "time": "2025-06-27T20:02:31+00:00" }, { "name": "symfony/http-client-contracts", @@ -10145,16 +10145,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae" + "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae", - "reference": "6b7c97fe1ddac8df3cc9ba6410c8abc683e148ae", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/452d19f945ee41345fd8a50c18b60783546b7bd3", + "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3", "shasum": "" }, "require": { @@ -10202,7 +10202,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.22" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.23" }, "funding": [ { @@ -10218,20 +10218,20 @@ "type": "tidelift" } ], - "time": "2025-05-11T15:36:20+00:00" + "time": "2025-05-26T09:17:58+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "15c105b839a7cfa1bc0989c091bfb6477f23b673" + "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/15c105b839a7cfa1bc0989c091bfb6477f23b673", - "reference": "15c105b839a7cfa1bc0989c091bfb6477f23b673", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2bb2cba685aabd859f22cf6946554e8e7f3c329a", + "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a", "shasum": "" }, "require": { @@ -10316,7 +10316,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.22" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.23" }, "funding": [ { @@ -10332,20 +10332,20 @@ "type": "tidelift" } ], - "time": "2025-05-29T07:23:40+00:00" + "time": "2025-06-28T08:14:51+00:00" }, { "name": "symfony/intl", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "aaecb52f18a6f95766a239ca0a6cc0df983d92cc" + "reference": "a3b12ce29a770d1f26c380dabf56a71bc2a88c84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/aaecb52f18a6f95766a239ca0a6cc0df983d92cc", - "reference": "aaecb52f18a6f95766a239ca0a6cc0df983d92cc", + "url": "https://api.github.com/repos/symfony/intl/zipball/a3b12ce29a770d1f26c380dabf56a71bc2a88c84", + "reference": "a3b12ce29a770d1f26c380dabf56a71bc2a88c84", "shasum": "" }, "require": { @@ -10399,7 +10399,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v6.4.22" + "source": "https://github.com/symfony/intl/tree/v6.4.23" }, "funding": [ { @@ -10415,20 +10415,20 @@ "type": "tidelift" } ], - "time": "2025-05-04T12:02:38+00:00" + "time": "2025-06-06T07:42:46+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.21", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "ada2809ccd4ec27aba9fc344e3efdaec624c6438" + "reference": "a480322ddf8e54de262c9bca31fdcbe26b553de5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/ada2809ccd4ec27aba9fc344e3efdaec624c6438", - "reference": "ada2809ccd4ec27aba9fc344e3efdaec624c6438", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a480322ddf8e54de262c9bca31fdcbe26b553de5", + "reference": "a480322ddf8e54de262c9bca31fdcbe26b553de5", "shasum": "" }, "require": { @@ -10479,7 +10479,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.21" + "source": "https://github.com/symfony/mailer/tree/v6.4.23" }, "funding": [ { @@ -10495,7 +10495,7 @@ "type": "tidelift" } ], - "time": "2025-04-26T23:47:35+00:00" + "time": "2025-06-26T21:24:02+00:00" }, { "name": "symfony/mime", @@ -12137,16 +12137,16 @@ }, { "name": "symfony/runtime", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "832c3ce3b810509815050434ccb7ead68d06395b" + "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/832c3ce3b810509815050434ccb7ead68d06395b", - "reference": "832c3ce3b810509815050434ccb7ead68d06395b", + "url": "https://api.github.com/repos/symfony/runtime/zipball/ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", + "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", "shasum": "" }, "require": { @@ -12196,7 +12196,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.4.22" + "source": "https://github.com/symfony/runtime/tree/v6.4.23" }, "funding": [ { @@ -12212,20 +12212,20 @@ "type": "tidelift" } ], - "time": "2025-05-07T21:15:03+00:00" + "time": "2025-06-13T07:44:14+00:00" }, { "name": "symfony/security-bundle", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "671ab5339a1e53923bfb8069bf984a47a412f612" + "reference": "3db1460f539b23e74a119981ea6b3002302250bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/671ab5339a1e53923bfb8069bf984a47a412f612", - "reference": "671ab5339a1e53923bfb8069bf984a47a412f612", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/3db1460f539b23e74a119981ea6b3002302250bc", + "reference": "3db1460f539b23e74a119981ea6b3002302250bc", "shasum": "" }, "require": { @@ -12308,7 +12308,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.4.22" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.23" }, "funding": [ { @@ -12324,20 +12324,20 @@ "type": "tidelift" } ], - "time": "2025-05-09T21:27:20+00:00" + "time": "2025-06-23T20:18:57+00:00" }, { "name": "symfony/security-core", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "110483f4e0106cf4bb63ed0479f6a5d09ab24a9e" + "reference": "527780a0482e592530174ca90e6189f64cdf6569" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/110483f4e0106cf4bb63ed0479f6a5d09ab24a9e", - "reference": "110483f4e0106cf4bb63ed0479f6a5d09ab24a9e", + "url": "https://api.github.com/repos/symfony/security-core/zipball/527780a0482e592530174ca90e6189f64cdf6569", + "reference": "527780a0482e592530174ca90e6189f64cdf6569", "shasum": "" }, "require": { @@ -12394,7 +12394,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.22" + "source": "https://github.com/symfony/security-core/tree/v6.4.23" }, "funding": [ { @@ -12410,7 +12410,7 @@ "type": "tidelift" } ], - "time": "2025-05-20T14:15:13+00:00" + "time": "2025-05-30T08:33:44+00:00" }, { "name": "symfony/security-csrf", @@ -12482,16 +12482,16 @@ }, { "name": "symfony/security-http", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "786c8eeee44b07419264ede2a795e8f490113dc2" + "reference": "815fcda8122a7850bf6d5d842ce03c20445295bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/786c8eeee44b07419264ede2a795e8f490113dc2", - "reference": "786c8eeee44b07419264ede2a795e8f490113dc2", + "url": "https://api.github.com/repos/symfony/security-http/zipball/815fcda8122a7850bf6d5d842ce03c20445295bb", + "reference": "815fcda8122a7850bf6d5d842ce03c20445295bb", "shasum": "" }, "require": { @@ -12550,7 +12550,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.4.22" + "source": "https://github.com/symfony/security-http/tree/v6.4.23" }, "funding": [ { @@ -12566,20 +12566,20 @@ "type": "tidelift" } ], - "time": "2025-05-09T07:11:47+00:00" + "time": "2025-06-23T20:18:57+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "b836df93e9ea07d1d3ada58a679ef205d54b64d1" + "reference": "b40a697a2bb2c3d841a1f9e34a8a9f50bf9d1d06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/b836df93e9ea07d1d3ada58a679ef205d54b64d1", - "reference": "b836df93e9ea07d1d3ada58a679ef205d54b64d1", + "url": "https://api.github.com/repos/symfony/serializer/zipball/b40a697a2bb2c3d841a1f9e34a8a9f50bf9d1d06", + "reference": "b40a697a2bb2c3d841a1f9e34a8a9f50bf9d1d06", "shasum": "" }, "require": { @@ -12648,7 +12648,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.22" + "source": "https://github.com/symfony/serializer/tree/v6.4.23" }, "funding": [ { @@ -12664,7 +12664,7 @@ "type": "tidelift" } ], - "time": "2025-05-12T08:02:50+00:00" + "time": "2025-06-27T15:34:20+00:00" }, { "name": "symfony/service-contracts", @@ -12751,16 +12751,16 @@ }, { "name": "symfony/stimulus-bundle", - "version": "v2.26.1", + "version": "v2.27.0", "source": { "type": "git", "url": "https://github.com/symfony/stimulus-bundle.git", - "reference": "82c174ebe564e6ecc1412974b6380b86d450675f" + "reference": "defaeb91bd366f9f43dbe54dbdfd9bc3c4138814" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/82c174ebe564e6ecc1412974b6380b86d450675f", - "reference": "82c174ebe564e6ecc1412974b6380b86d450675f", + "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/defaeb91bd366f9f43dbe54dbdfd9bc3c4138814", + "reference": "defaeb91bd366f9f43dbe54dbdfd9bc3c4138814", "shasum": "" }, "require": { @@ -12800,7 +12800,7 @@ "symfony-ux" ], "support": { - "source": "https://github.com/symfony/stimulus-bundle/tree/v2.26.1" + "source": "https://github.com/symfony/stimulus-bundle/tree/v2.27.0" }, "funding": [ { @@ -12816,7 +12816,7 @@ "type": "tidelift" } ], - "time": "2025-06-05T17:25:17+00:00" + "time": "2025-06-22T19:07:55+00:00" }, { "name": "symfony/stopwatch", @@ -12968,16 +12968,16 @@ }, { "name": "symfony/translation", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "7e3b3b7146c6fab36ddff304a8041174bf6e17ad" + "reference": "de8afa521e04a5220e9e58a1dc99971ab7cac643" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/7e3b3b7146c6fab36ddff304a8041174bf6e17ad", - "reference": "7e3b3b7146c6fab36ddff304a8041174bf6e17ad", + "url": "https://api.github.com/repos/symfony/translation/zipball/de8afa521e04a5220e9e58a1dc99971ab7cac643", + "reference": "de8afa521e04a5220e9e58a1dc99971ab7cac643", "shasum": "" }, "require": { @@ -13043,7 +13043,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.4.22" + "source": "https://github.com/symfony/translation/tree/v6.4.23" }, "funding": [ { @@ -13059,7 +13059,7 @@ "type": "tidelift" } ], - "time": "2025-05-29T07:06:44+00:00" + "time": "2025-06-26T21:24:02+00:00" }, { "name": "symfony/translation-contracts", @@ -13250,16 +13250,16 @@ }, { "name": "symfony/twig-bundle", - "version": "v6.4.13", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "c3beeb5336aba1ea03c37e526968c2fde3ef25c4" + "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/c3beeb5336aba1ea03c37e526968c2fde3ef25c4", - "reference": "c3beeb5336aba1ea03c37e526968c2fde3ef25c4", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/ef970ed7eb9e547d21628e4c803de0943759cbcd", + "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd", "shasum": "" }, "require": { @@ -13314,7 +13314,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.4.13" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.23" }, "funding": [ { @@ -13330,20 +13330,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2025-06-20T20:02:07+00:00" }, { "name": "symfony/uid", - "version": "v6.4.13", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007" + "reference": "9c8592da78d7ee6af52011eef593350d87e814c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/18eb207f0436a993fffbdd811b5b8fa35fa5e007", - "reference": "18eb207f0436a993fffbdd811b5b8fa35fa5e007", + "url": "https://api.github.com/repos/symfony/uid/zipball/9c8592da78d7ee6af52011eef593350d87e814c0", + "reference": "9c8592da78d7ee6af52011eef593350d87e814c0", "shasum": "" }, "require": { @@ -13388,7 +13388,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.13" + "source": "https://github.com/symfony/uid/tree/v6.4.23" }, "funding": [ { @@ -13404,20 +13404,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:18:03+00:00" + "time": "2025-06-26T08:06:12+00:00" }, { "name": "symfony/ux-translator", - "version": "v2.26.1", + "version": "v2.27.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-translator.git", - "reference": "e0c10aea8f2aa484db484710721035dc22d653c5" + "reference": "eacd8bef7652dcb3986e77243c860afe5a88266c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-translator/zipball/e0c10aea8f2aa484db484710721035dc22d653c5", - "reference": "e0c10aea8f2aa484db484710721035dc22d653c5", + "url": "https://api.github.com/repos/symfony/ux-translator/zipball/eacd8bef7652dcb3986e77243c860afe5a88266c", + "reference": "eacd8bef7652dcb3986e77243c860afe5a88266c", "shasum": "" }, "require": { @@ -13464,7 +13464,7 @@ "symfony-ux" ], "support": { - "source": "https://github.com/symfony/ux-translator/tree/v2.26.1" + "source": "https://github.com/symfony/ux-translator/tree/v2.27.0" }, "funding": [ { @@ -13480,20 +13480,20 @@ "type": "tidelift" } ], - "time": "2025-06-05T17:25:17+00:00" + "time": "2025-06-22T19:07:55+00:00" }, { "name": "symfony/ux-turbo", - "version": "v2.26.1", + "version": "v2.27.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-turbo.git", - "reference": "3754ac2b41220127e58c62f7599eaf7834b69a55" + "reference": "b9ce9b30a9cf9bbd090c7ad290bdaf84a0e100b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/3754ac2b41220127e58c62f7599eaf7834b69a55", - "reference": "3754ac2b41220127e58c62f7599eaf7834b69a55", + "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/b9ce9b30a9cf9bbd090c7ad290bdaf84a0e100b2", + "reference": "b9ce9b30a9cf9bbd090c7ad290bdaf84a0e100b2", "shasum": "" }, "require": { @@ -13563,7 +13563,7 @@ "turbo-stream" ], "support": { - "source": "https://github.com/symfony/ux-turbo/tree/v2.26.1" + "source": "https://github.com/symfony/ux-turbo/tree/v2.27.0" }, "funding": [ { @@ -13579,20 +13579,20 @@ "type": "tidelift" } ], - "time": "2025-06-05T17:25:17+00:00" + "time": "2025-06-06T20:27:21+00:00" }, { "name": "symfony/validator", - "version": "v6.4.22", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "4c5fbccb2d8f64017c8dada6473701a5c8539716" + "reference": "6506760ab57e7cda5bde9cdaed736526162284bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/4c5fbccb2d8f64017c8dada6473701a5c8539716", - "reference": "4c5fbccb2d8f64017c8dada6473701a5c8539716", + "url": "https://api.github.com/repos/symfony/validator/zipball/6506760ab57e7cda5bde9cdaed736526162284bc", + "reference": "6506760ab57e7cda5bde9cdaed736526162284bc", "shasum": "" }, "require": { @@ -13660,7 +13660,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.22" + "source": "https://github.com/symfony/validator/tree/v6.4.23" }, "funding": [ { @@ -13676,20 +13676,20 @@ "type": "tidelift" } ], - "time": "2025-05-29T07:03:46+00:00" + "time": "2025-06-26T07:25:45+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.21", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "22560f80c0c5cd58cc0bcaf73455ffd81eb380d5" + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/22560f80c0c5cd58cc0bcaf73455ffd81eb380d5", - "reference": "22560f80c0c5cd58cc0bcaf73455ffd81eb380d5", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", "shasum": "" }, "require": { @@ -13745,7 +13745,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.21" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.23" }, "funding": [ { @@ -13761,7 +13761,7 @@ "type": "tidelift" } ], - "time": "2025-04-09T07:34:50+00:00" + "time": "2025-06-27T15:05:27+00:00" }, { "name": "symfony/var-exporter", @@ -13997,16 +13997,16 @@ }, { "name": "symfony/yaml", - "version": "v6.4.21", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "f01987f45676778b474468aa266fe2eda1f2bc7e" + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/f01987f45676778b474468aa266fe2eda1f2bc7e", - "reference": "f01987f45676778b474468aa266fe2eda1f2bc7e", + "url": "https://api.github.com/repos/symfony/yaml/zipball/93e29e0deb5f1b2e360adfb389a20d25eb81a27b", + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b", "shasum": "" }, "require": { @@ -14049,7 +14049,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.21" + "source": "https://github.com/symfony/yaml/tree/v6.4.23" }, "funding": [ { @@ -14065,7 +14065,7 @@ "type": "tidelift" } ], - "time": "2025-04-04T09:48:44+00:00" + "time": "2025-06-03T06:46:12+00:00" }, { "name": "tecnickcom/tc-lib-barcode", @@ -15679,16 +15679,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.13.1", + "version": "1.13.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/faed855a7b5f4d4637717c2b3863e277116beb36", + "reference": "faed855a7b5f4d4637717c2b3863e277116beb36", "shasum": "" }, "require": { @@ -15727,7 +15727,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.3" }, "funding": [ { @@ -15735,7 +15735,7 @@ "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-07-05T12:25:42+00:00" }, { "name": "nikic/php-parser", @@ -16642,16 +16642,16 @@ }, { "name": "rector/rector", - "version": "2.0.18", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "be3a452085b524a04056e3dfe72d861948711062" + "reference": "d513dea45a94394b660e15c155d1fa27826f8e30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/be3a452085b524a04056e3dfe72d861948711062", - "reference": "be3a452085b524a04056e3dfe72d861948711062", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/d513dea45a94394b660e15c155d1fa27826f8e30", + "reference": "d513dea45a94394b660e15c155d1fa27826f8e30", "shasum": "" }, "require": { @@ -16681,6 +16681,7 @@ "MIT" ], "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "homepage": "https://getrector.com/", "keywords": [ "automation", "dev", @@ -16689,7 +16690,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.0.18" + "source": "https://github.com/rectorphp/rector/tree/2.1.0" }, "funding": [ { @@ -16697,7 +16698,7 @@ "type": "github" } ], - "time": "2025-06-11T11:19:37+00:00" + "time": "2025-06-24T20:26:57+00:00" }, { "name": "roave/security-advisories", @@ -16705,12 +16706,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "0a95bcf39c5b55601cb073bc307d567a16e31dc0" + "reference": "a76f62e135c8b583602bd99df737b5c20f4d7200" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0a95bcf39c5b55601cb073bc307d567a16e31dc0", - "reference": "0a95bcf39c5b55601cb073bc307d567a16e31dc0", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/a76f62e135c8b583602bd99df737b5c20f4d7200", + "reference": "a76f62e135c8b583602bd99df737b5c20f4d7200", "shasum": "" }, "conflict": { @@ -16780,7 +16781,7 @@ "bedita/bedita": "<4", "bednee/cooluri": "<1.0.30", "bigfork/silverstripe-form-capture": ">=3,<3.1.1", - "billz/raspap-webgui": "<=3.1.4", + "billz/raspap-webgui": "<3.3.6", "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", "blueimp/jquery-file-upload": "==6.4.4", "bmarshall511/wordpress_zero_spam": "<5.2.13", @@ -16816,9 +16817,9 @@ "ckeditor/ckeditor": "<4.25", "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", "co-stack/fal_sftp": "<0.2.6", - "cockpit-hq/cockpit": "<2.7|==2.7", + "cockpit-hq/cockpit": "<2.11.4", "codeception/codeception": "<3.1.3|>=4,<4.1.22", - "codeigniter/framework": "<3.1.9", + "codeigniter/framework": "<3.1.10", "codeigniter4/framework": "<4.5.8", "codeigniter4/shield": "<1.0.0.0-beta8", "codiad/codiad": "<=2.8.4", @@ -16982,7 +16983,7 @@ "gaoming13/wechat-php-sdk": "<=1.10.2", "genix/cms": "<=1.1.11", "georgringer/news": "<1.3.3", - "geshi/geshi": "<1.0.8.11-dev", + "geshi/geshi": "<=1.0.9.1", "getformwork/formwork": "<1.13.1|>=2.0.0.0-beta1,<2.0.0.0-beta4", "getgrav/grav": "<1.7.46", "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", @@ -17067,7 +17068,7 @@ "joyqi/hyper-down": "<=2.4.27", "jsdecena/laracom": "<2.0.9", "jsmitty12/phpwhois": "<5.1", - "juzaweb/cms": "<=3.4", + "juzaweb/cms": "<=3.4.2", "jweiland/events2": "<8.3.8|>=9,<9.0.6", "jweiland/kk-downloader": "<1.2.2", "kazist/phpwhois": "<=4.2.6", @@ -17118,7 +17119,7 @@ "luyadev/yii-helpers": "<1.2.1", "macropay-solutions/laravel-crud-wizard-free": "<3.4.17", "maestroerror/php-heic-to-jpg": "<1.0.5", - "magento/community-edition": "<2.4.5|==2.4.5|>=2.4.5.0-patch1,<2.4.5.0-patch12|==2.4.6|>=2.4.6.0-patch1,<2.4.6.0-patch10|>=2.4.7.0-beta1,<2.4.7.0-patch5|>=2.4.8.0-beta1,<2.4.8.0-beta2", + "magento/community-edition": "<2.4.5.0-patch13|==2.4.6|>=2.4.6.0-patch1,<2.4.6.0-patch11|>=2.4.7.0-beta1,<2.4.7.0-patch6|>=2.4.8.0-beta1,<2.4.8.0-patch1", "magento/core": "<=1.9.4.5", "magento/magento1ce": "<1.9.4.3-dev", "magento/magento1ee": ">=1,<1.14.4.3-dev", @@ -17294,7 +17295,7 @@ "processwire/processwire": "<=3.0.229", "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", "propel/propel1": ">=1,<=1.7.1", - "pterodactyl/panel": "<1.11.8", + "pterodactyl/panel": "<=1.11.10", "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", "ptrofimov/beanstalk_console": "<1.7.14", "pubnub/pubnub": "<6.1", @@ -17388,8 +17389,9 @@ "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "ssddanbrown/bookstack": "<24.05.1", - "starcitizentools/citizen-skin": ">=2.4.2,<3.3.1", - "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2", + "starcitizentools/citizen-skin": ">=1.9.4,<3.4", + "starcitizentools/short-description": ">=4,<4.0.1", + "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", "statamic/cms": "<=5.16", "stormpath/sdk": "<9.9.99", "studio-42/elfinder": "<=2.1.64", @@ -17651,7 +17653,7 @@ "type": "tidelift" } ], - "time": "2025-06-13T22:05:09+00:00" + "time": "2025-07-04T13:13:44+00:00" }, { "name": "sebastian/cli-parser", @@ -18760,16 +18762,16 @@ }, { "name": "symfony/maker-bundle", - "version": "v1.63.0", + "version": "v1.64.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "69478ab39bc303abfbe3293006a78b09a8512425" + "reference": "c86da84640b0586e92aee2b276ee3638ef2f425a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/69478ab39bc303abfbe3293006a78b09a8512425", - "reference": "69478ab39bc303abfbe3293006a78b09a8512425", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c86da84640b0586e92aee2b276ee3638ef2f425a", + "reference": "c86da84640b0586e92aee2b276ee3638ef2f425a", "shasum": "" }, "require": { @@ -18797,6 +18799,7 @@ "symfony/http-client": "^6.4|^7.0", "symfony/phpunit-bridge": "^6.4.1|^7.0", "symfony/security-core": "^6.4|^7.0", + "symfony/security-http": "^6.4|^7.0", "symfony/yaml": "^6.4|^7.0", "twig/twig": "^3.0|^4.x-dev" }, @@ -18832,7 +18835,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.63.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.64.0" }, "funding": [ { @@ -18848,20 +18851,20 @@ "type": "tidelift" } ], - "time": "2025-04-26T01:41:37+00:00" + "time": "2025-06-23T16:12:08+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v6.4.16", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "cebafe2f1ad2d1e745c1015b7c2519592341e4e6" + "reference": "0d26168bf78993b3c49e69e41bea3e7cbecc426c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/cebafe2f1ad2d1e745c1015b7c2519592341e4e6", - "reference": "cebafe2f1ad2d1e745c1015b7c2519592341e4e6", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/0d26168bf78993b3c49e69e41bea3e7cbecc426c", + "reference": "0d26168bf78993b3c49e69e41bea3e7cbecc426c", "shasum": "" }, "require": { @@ -18913,8 +18916,11 @@ ], "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", + "keywords": [ + "testing" + ], "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.16" + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.23" }, "funding": [ { @@ -18930,7 +18936,7 @@ "type": "tidelift" } ], - "time": "2024-11-13T15:06:22+00:00" + "time": "2025-06-04T07:29:26+00:00" }, { "name": "symfony/web-profiler-bundle", @@ -19137,7 +19143,6 @@ "minimum-stability": "stable", "stability-flags": { "florianv/swap-bundle": 20, - "jbtronics/settings-bundle": 20, "roave/security-advisories": 20 }, "prefer-stable": false, diff --git a/config/packages/knpu_oauth2_client.yaml b/config/packages/knpu_oauth2_client.yaml index 7d296a8b..5e56d5c5 100644 --- a/config/packages/knpu_oauth2_client.yaml +++ b/config/packages/knpu_oauth2_client.yaml @@ -6,8 +6,8 @@ knpu_oauth2_client: type: generic provider_class: '\League\OAuth2\Client\Provider\GenericProvider' - client_id: '%env(PROVIDER_DIGIKEY_CLIENT_ID)%' - client_secret: '%env(PROVIDER_DIGIKEY_SECRET)%' + client_id: '%env(settings:digikey:clientId)%' + client_secret: '%env(settings:digikey:secret)%' redirect_route: 'oauth_client_check' redirect_params: {name: 'ip_digikey_oauth'} @@ -26,8 +26,8 @@ knpu_oauth2_client: type: generic provider_class: '\League\OAuth2\Client\Provider\GenericProvider' - client_id: '%env(PROVIDER_OCTOPART_CLIENT_ID)%' - client_secret: '%env(PROVIDER_OCTOPART_SECRET)%' + client_id: '%env(settings:octopart:clientId)%' + client_secret: '%env(settings:octopart:secret)%' redirect_route: 'oauth_client_check' redirect_params: { name: 'ip_octopart_oauth' } diff --git a/config/packages/settings.yaml b/config/packages/settings.yaml index 6b47cba3..05e21636 100644 --- a/config/packages/settings.yaml +++ b/config/packages/settings.yaml @@ -1,2 +1,8 @@ jbtronics_settings: - default_storage_adapter: Jbtronics\SettingsBundle\Storage\PHPFileStorageAdapter \ No newline at end of file + default_storage_adapter: Jbtronics\SettingsBundle\Storage\ORMStorageAdapter + + cache: + default_cacheable: true + + orm_storage: + default_entity_class: App\Entity\SettingsEntry \ No newline at end of file diff --git a/config/packages/swap.yaml b/config/packages/swap.yaml index 2767f740..beb41d26 100644 --- a/config/packages/swap.yaml +++ b/config/packages/swap.yaml @@ -6,5 +6,5 @@ florianv_swap: providers: european_central_bank: ~ # European Central Bank (only works for EUR base currency) fixer: # Fixer.io (needs an API key) - access_key: "%env(FIXER_API_KEY)%" + access_key: "%env(string:default:settings:exchange_rate:fixerApiKey:INVALID)%" #exchange_rates_api: ~ \ No newline at end of file diff --git a/config/permissions.yaml b/config/permissions.yaml index b8970556..e5a1d65b 100644 --- a/config/permissions.yaml +++ b/config/permissions.yaml @@ -265,17 +265,13 @@ perms: # Here comes a list with all Permission names (they have a perm_[name] co # label: "perm.database.write_db_settings" # alsoSet: ['read_db_settings', 'see_status'] - #config: - # label: "perm.config" - # group: "system" - # operations: - # read_config: - # label: "perm.config.read_config" - # edit_config: - # label: "perm.config.edit_config" - # alsoSet: 'read_config' - # server_info: - # label: "perm.config.server_info" + config: + label: "perm.config" + group: "system" + operations: + change_system_settings: + label: "perm.config.change_system_settings" + apiTokenRole: ROLE_API_ADMIN system: label: "perm.system" diff --git a/config/services.yaml b/config/services.yaml index dfc9a7c7..6133dce7 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -199,23 +199,6 @@ services: arguments: $providers: !tagged_iterator 'app.info_provider' - App\Services\InfoProviderSystem\Providers\DigikeyProvider: - arguments: - $clientId: '%env(string:PROVIDER_DIGIKEY_CLIENT_ID)%' - $currency: '%env(string:PROVIDER_DIGIKEY_CURRENCY)%' - $language: '%env(string:PROVIDER_DIGIKEY_LANGUAGE)%' - $country: '%env(string:PROVIDER_DIGIKEY_COUNTRY)%' - - App\Services\InfoProviderSystem\Providers\OctopartProvider: - arguments: - $clientId: '&env(string:PROVIDER_OCTOPART_CLIENT_ID)%' - $secret: '%env(string:PROVIDER_OCTOPART_SECRET)%' - $country: '%env(string:PROVIDER_OCTOPART_COUNTRY)%' - $currency: '%env(string:PROVIDER_OCTOPART_CURRENCY)%' - $search_limit: '%env(int:PROVIDER_OCTOPART_SEARCH_LIMIT)%' - $onlyAuthorizedSellers: '%env(bool:PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS)%' - - #################################################################################################################### # API system #################################################################################################################### diff --git a/docs/configuration.md b/docs/configuration.md index 0ad30a00..b4e5efc4 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -95,6 +95,8 @@ bundled with Part-DB. Set `DATABASE_MYSQL_SSL_VERIFY_CERT` if you want to accept particularly for securing and protecting various aspects of your application. It's a secret key that is used for cryptographic operations and security measures (session management, CSRF protection, etc..). Therefore this value should be handled as confidential data and not shared publicly. +* `SHOW_PART_IMAGE_OVERLAY`: Set to 0 to disable the part image overlay, which appears if you hover over an image in the + part image gallery ### E-Mail settings diff --git a/migrations/Version20250706201121.php b/migrations/Version20250706201121.php new file mode 100644 index 00000000..b7563978 --- /dev/null +++ b/migrations/Version20250706201121.php @@ -0,0 +1,49 @@ +addSql('CREATE TABLE settings_entry (`key` VARCHAR(255) NOT NULL, `data` JSON DEFAULT NULL, id INT AUTO_INCREMENT NOT NULL, UNIQUE INDEX UNIQ_93F8DB394E645A7E (`key`), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci`'); + + } + + public function mySQLDown(Schema $schema): void + { + $this->addSql('DROP TABLE settings_entry'); + } + + public function sqLiteUp(Schema $schema): void + { + $this->addSql('CREATE TABLE settings_entry ("key" VARCHAR(255) NOT NULL, "data" CLOB DEFAULT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_93F8DB39F48571EB ON settings_entry ("key")'); + } + + public function sqLiteDown(Schema $schema): void + { + $this->addSql('DROP TABLE settings_entry'); + } + + public function postgreSQLUp(Schema $schema): void + { + $this->addSql('CREATE TABLE settings_entry ("key" VARCHAR(255) NOT NULL, "data" JSON DEFAULT NULL, id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE UNIQUE INDEX UNIQ_93F8DB39F48571EB ON settings_entry ("key")'); + } + + public function postgreSQLDown(Schema $schema): void + { + $this->addSql('DROP TABLE settings_entry'); + } +} diff --git a/src/Controller/SettingsController.php b/src/Controller/SettingsController.php index 3b0eb15c..1da8a443 100644 --- a/src/Controller/SettingsController.php +++ b/src/Controller/SettingsController.php @@ -40,6 +40,8 @@ class SettingsController extends AbstractController #[Route("/settings", name: "system_settings")] public function systemSettings(Request $request, TagAwareCacheInterface $cache): Response { + $this->denyAccessUnlessGranted('@config.change_system_settings'); + //Create a clone of the settings object $settings = $this->settingsManager->createTemporaryCopy(AppSettings::class); @@ -62,9 +64,6 @@ class SettingsController extends AbstractController $cache->invalidateTags(['tree_treeview', 'sidebar_tree_update']); } - - - //Render the form return $this->render('settings/settings.html.twig', [ 'form' => $form diff --git a/src/Entity/Parameters/AbstractParameter.php b/src/Entity/Parameters/AbstractParameter.php index edcedc3e..39f333da 100644 --- a/src/Entity/Parameters/AbstractParameter.php +++ b/src/Entity/Parameters/AbstractParameter.php @@ -217,7 +217,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu $str = ''; $bracket_opened = false; - if ($this->value_typical) { + if ($this->value_typical !== null) { $str .= $this->getValueTypicalWithUnit($latex_formatted); if ($this->value_min || $this->value_max) { $bracket_opened = true; @@ -225,11 +225,11 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu } } - if ($this->value_max && $this->value_min) { + if ($this->value_max !== null && $this->value_min !== null) { $str .= $this->getValueMinWithUnit($latex_formatted).' ... '.$this->getValueMaxWithUnit($latex_formatted); - } elseif ($this->value_max) { + } elseif ($this->value_max !== null) { $str .= 'max. '.$this->getValueMaxWithUnit($latex_formatted); - } elseif ($this->value_min) { + } elseif ($this->value_min !== null) { $str .= 'min. '.$this->getValueMinWithUnit($latex_formatted); } @@ -449,7 +449,10 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu if (!$with_latex) { $unit = $this->unit; } else { - $unit = '$\mathrm{'.$this->unit.'}$'; + //Escape the percentage sign for convenience (as latex uses it as comment and it is often used in units) + $escaped = preg_replace('/\\\\?%/', "\\\\%", $this->unit); + + $unit = '$\mathrm{'.$escaped.'}$'; } return $str.' '.$unit; @@ -457,7 +460,7 @@ abstract class AbstractParameter extends AbstractNamedDBElement implements Uniqu return $str; } - + /** * Returns the class of the element that is allowed to be associated with this attachment. * @return string diff --git a/src/Entity/SettingsEntry.php b/src/Entity/SettingsEntry.php new file mode 100644 index 00000000..488de1d1 --- /dev/null +++ b/src/Entity/SettingsEntry.php @@ -0,0 +1,35 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Entity; + +use Doctrine\DBAL\Types\Types; +use Jbtronics\SettingsBundle\Entity\AbstractSettingsORMEntry; +use Doctrine\ORM\Mapping as ORM; + +#[ORM\Entity] +class SettingsEntry extends AbstractSettingsORMEntry +{ + #[ORM\Id, ORM\GeneratedValue, ORM\Column(type: Types::INTEGER)] + protected int $id; +} \ No newline at end of file diff --git a/src/Services/EDA/KiCadHelper.php b/src/Services/EDA/KiCadHelper.php index 3285e705..75c2cc34 100644 --- a/src/Services/EDA/KiCadHelper.php +++ b/src/Services/EDA/KiCadHelper.php @@ -241,6 +241,49 @@ class KiCadHelper $result["fields"]["Part-DB IPN"] = $this->createField($part->getIpn()); } + // Add supplier information from orderdetails (include obsolete orderdetails) + if ($part->getOrderdetails(false)->count() > 0) { + $supplierCounts = []; + + foreach ($part->getOrderdetails(false) as $orderdetail) { + if ($orderdetail->getSupplier() !== null && $orderdetail->getSupplierPartNr() !== '') { + $supplierName = $orderdetail->getSupplier()->getName(); + + $supplierName .= " SPN"; // Append "SPN" to the supplier name to indicate Supplier Part Number + + if (!isset($supplierCounts[$supplierName])) { + $supplierCounts[$supplierName] = 0; + } + $supplierCounts[$supplierName]++; + + // Create field name with sequential number if more than one from same supplier (e.g. "Mouser", "Mouser 2", etc.) + $fieldName = $supplierCounts[$supplierName] > 1 + ? $supplierName . ' ' . $supplierCounts[$supplierName] + : $supplierName; + + $result["fields"][$fieldName] = $this->createField($orderdetail->getSupplierPartNr()); + } + } + } + + //Add fields for KiCost: + if ($part->getManufacturer() !== null) { + $result["fields"]["manf"] = $this->createField($part->getManufacturer()->getName()); + } + if ($part->getManufacturerProductNumber() !== "") { + $result['fields']['manf#'] = $this->createField($part->getManufacturerProductNumber()); + } + + //For each supplier, add a field with the supplier name and the supplier part number for KiCost + if ($part->getOrderdetails(false)->count() > 0) { + foreach ($part->getOrderdetails(false) as $orderdetail) { + if ($orderdetail->getSupplier() !== null && $orderdetail->getSupplierPartNr() !== '') { + $fieldName = mb_strtolower($orderdetail->getSupplier()->getName()) . '#'; + + $result["fields"][$fieldName] = $this->createField($orderdetail->getSupplierPartNr()); + } + } + } return $result; } diff --git a/src/Services/InfoProviderSystem/Providers/DigikeyProvider.php b/src/Services/InfoProviderSystem/Providers/DigikeyProvider.php index b20368ce..c2113b4d 100644 --- a/src/Services/InfoProviderSystem/Providers/DigikeyProvider.php +++ b/src/Services/InfoProviderSystem/Providers/DigikeyProvider.php @@ -31,6 +31,7 @@ use App\Services\InfoProviderSystem\DTOs\PriceDTO; use App\Services\InfoProviderSystem\DTOs\PurchaseInfoDTO; use App\Services\InfoProviderSystem\DTOs\SearchResultDTO; use App\Services\OAuth\OAuthTokenManager; +use App\Settings\InfoProviderSystem\DigikeySettings; use Symfony\Contracts\HttpClient\HttpClientInterface; class DigikeyProvider implements InfoProviderInterface @@ -55,17 +56,16 @@ class DigikeyProvider implements InfoProviderInterface ]; public function __construct(HttpClientInterface $httpClient, private readonly OAuthTokenManager $authTokenManager, - private readonly string $currency, private readonly string $clientId, - private readonly string $language, private readonly string $country) + private readonly DigikeySettings $settings,) { //Create the HTTP client with some default options $this->digikeyClient = $httpClient->withOptions([ "base_uri" => self::BASE_URI, "headers" => [ - "X-DIGIKEY-Client-Id" => $clientId, - "X-DIGIKEY-Locale-Site" => $this->country, - "X-DIGIKEY-Locale-Language" => $this->language, - "X-DIGIKEY-Locale-Currency" => $this->currency, + "X-DIGIKEY-Client-Id" => $this->settings->clientId, + "X-DIGIKEY-Locale-Site" => $this->settings->country, + "X-DIGIKEY-Locale-Language" => $this->settings->language, + "X-DIGIKEY-Locale-Currency" => $this->settings->currency, "X-DIGIKEY-Customer-Id" => 0, ] ]); @@ -101,7 +101,7 @@ class DigikeyProvider implements InfoProviderInterface public function isActive(): bool { //The client ID has to be set and a token has to be available (user clicked connect) - return $this->clientId !== '' && $this->authTokenManager->hasToken(self::OAUTH_APP_NAME); + return $this->settings->clientId !== '' && $this->authTokenManager->hasToken(self::OAUTH_APP_NAME); } public function searchByKeyword(string $keyword): array @@ -268,7 +268,7 @@ class DigikeyProvider implements InfoProviderInterface $prices = []; foreach ($price_breaks as $price_break) { - $prices[] = new PriceDTO(minimum_discount_amount: $price_break['BreakQuantity'], price: (string) $price_break['UnitPrice'], currency_iso_code: $this->currency); + $prices[] = new PriceDTO(minimum_discount_amount: $price_break['BreakQuantity'], price: (string) $price_break['UnitPrice'], currency_iso_code: $this->settings->currency); } return [ diff --git a/src/Services/InfoProviderSystem/Providers/OctopartProvider.php b/src/Services/InfoProviderSystem/Providers/OctopartProvider.php index e28162ba..ce1ec4a4 100644 --- a/src/Services/InfoProviderSystem/Providers/OctopartProvider.php +++ b/src/Services/InfoProviderSystem/Providers/OctopartProvider.php @@ -30,6 +30,7 @@ use App\Services\InfoProviderSystem\DTOs\PartDetailDTO; use App\Services\InfoProviderSystem\DTOs\PriceDTO; use App\Services\InfoProviderSystem\DTOs\PurchaseInfoDTO; use App\Services\OAuth\OAuthTokenManager; +use App\Settings\InfoProviderSystem\OctopartSettings; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\HttpClient\HttpOptions; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -114,9 +115,8 @@ class OctopartProvider implements InfoProviderInterface public function __construct(private readonly HttpClientInterface $httpClient, private readonly OAuthTokenManager $authTokenManager, private readonly CacheItemPoolInterface $partInfoCache, - private readonly string $clientId, private readonly string $secret, - private readonly string $currency, private readonly string $country, - private readonly int $search_limit, private readonly bool $onlyAuthorizedSellers) + private readonly OctopartSettings $settings, + ) { } @@ -183,7 +183,7 @@ class OctopartProvider implements InfoProviderInterface { //The client ID has to be set and a token has to be available (user clicked connect) //return /*!empty($this->clientId) && */ $this->authTokenManager->hasToken(self::OAUTH_APP_NAME); - return $this->clientId !== '' && $this->secret !== ''; + return $this->settings->clientId !== '' && $this->settings->secret !== ''; } private function mapLifeCycleStatus(?string $value): ?ManufacturingStatus @@ -347,10 +347,10 @@ class OctopartProvider implements InfoProviderInterface $result = $this->makeGraphQLCall($graphQL, [ 'keyword' => $keyword, - 'limit' => $this->search_limit, - 'currency' => $this->currency, - 'country' => $this->country, - 'authorizedOnly' => $this->onlyAuthorizedSellers, + 'limit' => $this->settings->searchLimit, + 'currency' => $this->settings->currency, + 'country' => $this->settings->country, + 'authorizedOnly' => $this->settings->onlyAuthorizedSellers, ]); $tmp = []; @@ -383,9 +383,9 @@ class OctopartProvider implements InfoProviderInterface $result = $this->makeGraphQLCall($graphql, [ 'ids' => [$id], - 'currency' => $this->currency, - 'country' => $this->country, - 'authorizedOnly' => $this->onlyAuthorizedSellers, + 'currency' => $this->settings->currency, + 'country' => $this->settings->country, + 'authorizedOnly' => $this->settings->onlyAuthorizedSellers, ]); $tmp = $this->partResultToDTO($result['data']['supParts'][0]); diff --git a/src/Services/Trees/ToolsTreeBuilder.php b/src/Services/Trees/ToolsTreeBuilder.php index 18571306..f7a9d1c4 100644 --- a/src/Services/Trees/ToolsTreeBuilder.php +++ b/src/Services/Trees/ToolsTreeBuilder.php @@ -289,6 +289,13 @@ class ToolsTreeBuilder ))->setIcon('fa-fw fa-treeview fa-solid fa-database'); } + if ($this->security->isGranted('@config.change_system_settings')) { + $nodes[] = (new TreeViewNode( + $this->translator->trans('tree.tools.system.settings'), + $this->urlGenerator->generate('system_settings') + ))->setIcon('fa fa-fw fa-gears fa-solid'); + } + return $nodes; } } diff --git a/src/Services/Trees/TreeViewGenerator.php b/src/Services/Trees/TreeViewGenerator.php index 9fb32522..73ffa5ba 100644 --- a/src/Services/Trees/TreeViewGenerator.php +++ b/src/Services/Trees/TreeViewGenerator.php @@ -179,10 +179,7 @@ class TreeViewGenerator } if (($mode === 'list_parts_root' || $mode === 'devices') && $this->rootNodeEnabled) { - //We show the root node as a link to the list of all parts - $show_all_parts_url = $this->router->generate('parts_show_all'); - - $root_node = new TreeViewNode($this->entityClassToRootNodeString($class), $show_all_parts_url, $generic); + $root_node = new TreeViewNode($this->entityClassToRootNodeString($class), $this->entityClassToRootNodeHref($class), $generic); $root_node->setExpanded($this->rootNodeExpandedByDefault); $root_node->setIcon($this->entityClassToRootNodeIcon($class)); @@ -192,6 +189,27 @@ class TreeViewGenerator return array_merge($head, $generic); } + protected function entityClassToRootNodeHref(string $class): ?string + { + //If the root node should redirect to the new entity page, we return the URL for the new entity. + if ($this->sidebarSettings->rootNodeRedirectsToNewEntity) { + return match ($class) { + Category::class => $this->router->generate('category_new'), + StorageLocation::class => $this->router->generate('store_location_new'), + Footprint::class => $this->router->generate('footprint_new'), + Manufacturer::class => $this->router->generate('manufacturer_new'), + Supplier::class => $this->router->generate('supplier_new'), + Project::class => $this->router->generate('project_new'), + default => null, + }; + } + + return match ($class) { + Project::class => $this->router->generate('project_new'), + default => $this->router->generate('parts_show_all') + }; + } + protected function entityClassToRootNodeString(string $class): string { return match ($class) { diff --git a/src/Services/UserSystem/PermissionPresetsHelper.php b/src/Services/UserSystem/PermissionPresetsHelper.php index eeb80f61..554da8b3 100644 --- a/src/Services/UserSystem/PermissionPresetsHelper.php +++ b/src/Services/UserSystem/PermissionPresetsHelper.php @@ -105,6 +105,9 @@ class PermissionPresetsHelper $this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'suppliers', PermissionData::ALLOW); $this->permissionResolver->setAllOperationsOfPermission($perm_holder, 'projects', PermissionData::ALLOW); + //Allow to change system settings + $this->permissionResolver->setPermission($perm_holder, 'config', 'change_system_settings', PermissionData::ALLOW); + //Allow to manage Oauth tokens $this->permissionResolver->setPermission($perm_holder, 'system', 'manage_oauth_tokens', PermissionData::ALLOW); //Allow to show updates diff --git a/src/Settings/BehaviorSettings/BehaviorSettings.php b/src/Settings/BehaviorSettings/BehaviorSettings.php index 97a1759e..1251a097 100644 --- a/src/Settings/BehaviorSettings/BehaviorSettings.php +++ b/src/Settings/BehaviorSettings/BehaviorSettings.php @@ -37,4 +37,7 @@ class BehaviorSettings #[EmbeddedSettings] public ?TableSettings $table = null; + + #[EmbeddedSettings] + public ?PartInfoSettings $partInfo = null; } \ No newline at end of file diff --git a/src/Settings/BehaviorSettings/PartInfoSettings.php b/src/Settings/BehaviorSettings/PartInfoSettings.php new file mode 100644 index 00000000..4c44b9bb --- /dev/null +++ b/src/Settings/BehaviorSettings/PartInfoSettings.php @@ -0,0 +1,43 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\BehaviorSettings; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Symfony\Component\Translation\TranslatableMessage as TM; + +#[Settings(name: "part_info", label: new TM("settings.behavior.part_info"))] +#[SettingsIcon('fa-circle-info')] +class PartInfoSettings +{ + /** + * Whether to show the part image overlays in the part info view + * @var bool + */ + #[SettingsParameter(label: new TM("settings.behavior.part_info.show_part_image_overlay"), description: new TM("settings.behavior.part_info.show_part_image_overlay.help"), + envVar: "bool:SHOW_PART_IMAGE_OVERLAY", envVarMode: EnvVarMode::OVERWRITE)] + public bool $showPartImageOverlay = true; +} \ No newline at end of file diff --git a/src/Settings/BehaviorSettings/SidebarSettings.php b/src/Settings/BehaviorSettings/SidebarSettings.php index 3e93d634..1266fa47 100644 --- a/src/Settings/BehaviorSettings/SidebarSettings.php +++ b/src/Settings/BehaviorSettings/SidebarSettings.php @@ -67,4 +67,10 @@ class SidebarSettings */ #[SettingsParameter(label: new TM("settings.behavior.sidebar.rootNodeExpanded"))] public bool $rootNodeExpanded = true; + + /** + * @var bool Whether the root node should redirect to a new entity creation page when clicked. + */ + #[SettingsParameter(label: new TM("settings.behavior.sidebar.rootNodeRedirectsToNewEntity"))] + public bool $rootNodeRedirectsToNewEntity = false; } \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/DigikeySettings.php b/src/Settings/InfoProviderSystem/DigikeySettings.php new file mode 100644 index 00000000..17d05c5b --- /dev/null +++ b/src/Settings/InfoProviderSystem/DigikeySettings.php @@ -0,0 +1,70 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\InfoProviderSystem; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsTrait; +use Symfony\Component\Form\Extension\Core\Type\CountryType; +use Symfony\Component\Form\Extension\Core\Type\CurrencyType; +use Symfony\Component\Form\Extension\Core\Type\LanguageType; +use Symfony\Component\Translation\TranslatableMessage as TM; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Symfony\Component\Validator\Constraints as Assert; + +#[Settings(label: new TM("settings.ips.digikey"))] +#[SettingsIcon("fa-plug")] +class DigikeySettings +{ + use SettingsTrait; + + #[SettingsParameter( + label: new TM("settings.ips.digikey.client_id"), + envVar: "PROVIDER_DIGIKEY_CLIENT_ID", envVarMode: EnvVarMode::OVERWRITE + )] + public ?string $clientId = null; + + #[SettingsParameter( + label: new TM("settings.ips.digikey.secret"), + envVar: "PROVIDER_DIGIKEY_SECRET", envVarMode: EnvVarMode::OVERWRITE + )] + public ?string $secret = null; + + #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, + formOptions: ["preferred_choices" => ["EUR", "USD", "CHF", "GBP"]], + envVar: "PROVIDER_DIGIKEY_CURRENCY", envVarMode: EnvVarMode::OVERWRITE)] + #[Assert\Currency()] + public string $currency = "EUR"; + + #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, + envVar: "PROVIDER_DIGIKEY_COUNTRY", envVarMode: EnvVarMode::OVERWRITE)] + #[Assert\Country] + public string $country = "DE"; + + #[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class, + envVar: "PROVIDER_DIGIKEY_LANGUAGE", envVarMode: EnvVarMode::OVERWRITE)] + #[Assert\Language] + public string $language = "en"; +} \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/Element14Settings.php b/src/Settings/InfoProviderSystem/Element14Settings.php index 8ca38425..42e2de5d 100644 --- a/src/Settings/InfoProviderSystem/Element14Settings.php +++ b/src/Settings/InfoProviderSystem/Element14Settings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Jbtronics\SettingsBundle\Settings\SettingsTrait; @@ -35,9 +36,11 @@ class Element14Settings { use SettingsTrait; - #[SettingsParameter(label: new TM("settings.ips.element14.apiKey"), description: new TM("settings.ips.element14.apiKey.help"), formOptions: ["help_html" => true], envVar: "PROVIDER_ELEMENT14_KEY")] + #[SettingsParameter(label: new TM("settings.ips.element14.apiKey"), description: new TM("settings.ips.element14.apiKey.help"), + formOptions: ["help_html" => true], envVar: "PROVIDER_ELEMENT14_KEY", envVarMode: EnvVarMode::OVERWRITE)] public ?string $apiKey = null; - #[SettingsParameter(label: new TM("settings.ips.element14.storeId"), description: new TM("settings.ips.element14.storeId.help"), formOptions: ["help_html" => true], envVar: "PROVIDER_ELEMENT14_STORE_ID")] + #[SettingsParameter(label: new TM("settings.ips.element14.storeId"), description: new TM("settings.ips.element14.storeId.help"), + formOptions: ["help_html" => true], envVar: "PROVIDER_ELEMENT14_STORE_ID", envVarMode: EnvVarMode::OVERWRITE)] public string $storeId = "de.farnell.com"; } \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/InfoProviderSettings.php b/src/Settings/InfoProviderSystem/InfoProviderSettings.php index 109fbc02..3c7159cb 100644 --- a/src/Settings/InfoProviderSystem/InfoProviderSettings.php +++ b/src/Settings/InfoProviderSystem/InfoProviderSettings.php @@ -32,6 +32,9 @@ class InfoProviderSettings { use SettingsTrait; + #[EmbeddedSettings] + public ?DigikeySettings $digikey = null; + #[EmbeddedSettings] public ?MouserSettings $mouser = null; @@ -41,6 +44,9 @@ class InfoProviderSettings #[EmbeddedSettings] public ?Element14Settings $element14 = null; + #[EmbeddedSettings] + public ?OctopartSettings $octopartSettings = null; + #[EmbeddedSettings] public ?LCSCSettings $lcsc = null; diff --git a/src/Settings/InfoProviderSystem/LCSCSettings.php b/src/Settings/InfoProviderSystem/LCSCSettings.php index ac4a47f4..906838e2 100644 --- a/src/Settings/InfoProviderSystem/LCSCSettings.php +++ b/src/Settings/InfoProviderSystem/LCSCSettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Jbtronics\SettingsBundle\Settings\SettingsTrait; @@ -37,10 +38,12 @@ class LCSCSettings { use SettingsTrait; - #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), envVar: "bool:PROVIDER_LCSC_ENABLED")] + #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), + envVar: "bool:PROVIDER_LCSC_ENABLED", envVarMode: EnvVarMode::OVERWRITE)] public bool $enabled = false; - #[SettingsParameter(label: new TM("settings.ips.lcsc.currency"), formType: CurrencyType::class, envVar: "string:PROVIDER_LCSC_CURRENCY")] + #[SettingsParameter(label: new TM("settings.ips.lcsc.currency"), formType: CurrencyType::class, + envVar: "string:PROVIDER_LCSC_CURRENCY", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Currency()] public string $currency = 'EUR'; } \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/MouserSettings.php b/src/Settings/InfoProviderSystem/MouserSettings.php index 5407620d..b84deb50 100644 --- a/src/Settings/InfoProviderSystem/MouserSettings.php +++ b/src/Settings/InfoProviderSystem/MouserSettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Symfony\Component\Validator\Constraints as Assert; @@ -33,22 +34,25 @@ use Symfony\Component\Translation\TranslatableMessage as TM; #[SettingsIcon("fa-plug")] class MouserSettings { - #[SettingsParameter(label: new TM("settings.ips.mouser.apiKey"), description: new TM("settings.ips.mouser.apiKey.help"), formOptions: ["help_html" => true], envVar: "PROVIDER_MOUSER_KEY")] + #[SettingsParameter(label: new TM("settings.ips.mouser.apiKey"), description: new TM("settings.ips.mouser.apiKey.help"), + formOptions: ["help_html" => true], envVar: "PROVIDER_MOUSER_KEY", envVarMode: EnvVarMode::OVERWRITE)] public ?string $apiKey = null; /** @var int The number of results to get from Mouser while searching (please note that this value is max 50) */ - #[SettingsParameter(label: new TM("settings.ips.mouser.searchLimit"), description: new TM("settings.ips.mouser.searchLimit.help"), envVar: "int:PROVIDER_MOUSER_SEARCH_LIMIT")] + #[SettingsParameter(label: new TM("settings.ips.mouser.searchLimit"), description: new TM("settings.ips.mouser.searchLimit.help"), + envVar: "int:PROVIDER_MOUSER_SEARCH_LIMIT", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Range(min: 1, max: 50)] public int $searchLimit = 50; /** @var MouserSearchOptions Filter search results by RoHS compliance and stock availability */ - #[SettingsParameter(label: new TM("settings.ips.mouser.searchOptions"), description: new TM("settings.ips.mouser.searchOptions.help"), envVar: "PROVIDER_MOUSER_SEARCH_OPTION", envVarMapper: [self::class, "mapSearchOptionEnvVar"])] + #[SettingsParameter(label: new TM("settings.ips.mouser.searchOptions"), description: new TM("settings.ips.mouser.searchOptions.help"), + envVar: "PROVIDER_MOUSER_SEARCH_OPTION", envVarMode: EnvVarMode::OVERWRITE, envVarMapper: [self::class, "mapSearchOptionEnvVar"])] public MouserSearchOptions $searchOption = MouserSearchOptions::NONE; /** @var bool It is recommended to leave this set to 'true'. The option is not really documented by Mouser: * Used when searching for keywords in the language specified when you signed up for Search API. */ //TODO: Put this into some expert mode only - #[SettingsParameter(envVar: "bool:PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE")] + //#[SettingsParameter(envVar: "bool:PROVIDER_MOUSER_SEARCH_WITH_SIGNUP_LANGUAGE")] public bool $searchWithSignUpLanguage = true; public static function mapSearchOptionEnvVar(?string $value): MouserSearchOptions diff --git a/src/Settings/InfoProviderSystem/OEMSecretsSettings.php b/src/Settings/InfoProviderSystem/OEMSecretsSettings.php index dfb2d689..75c2c821 100644 --- a/src/Settings/InfoProviderSystem/OEMSecretsSettings.php +++ b/src/Settings/InfoProviderSystem/OEMSecretsSettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Jbtronics\SettingsBundle\Settings\SettingsTrait; @@ -41,14 +42,17 @@ class OEMSecretsSettings public const SUPPORTED_CURRENCIES = ["AUD", "CAD", "CHF", "CNY", "DKK", "EUR", "GBP", "HKD", "ILS", "INR", "JPY", "KRW", "NOK", "NZD", "RUB", "SEK", "SGD", "TWD", "USD"]; - #[SettingsParameter(label: new TM("settings.ips.element14.apiKey"), envVar: "PROVIDER_OEMSECRETS_KEY")] + #[SettingsParameter(label: new TM("settings.ips.element14.apiKey"), + envVar: "PROVIDER_OEMSECRETS_KEY", envVarMode: EnvVarMode::OVERWRITE)] public ?string $apiKey = null; #[Assert\Country] - #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR", "US"]], envVar: "PROVIDER_OEMSECRETS_COUNTRY_CODE")] + #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR", "US"]], + envVar: "PROVIDER_OEMSECRETS_COUNTRY_CODE", envVarMode: EnvVarMode::OVERWRITE)] public ?string $country = "DE"; - #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => self::SUPPORTED_CURRENCIES], envVar: "PROVIDER_OEMSECRETS_CURRENCY")] + #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => self::SUPPORTED_CURRENCIES], + envVar: "PROVIDER_OEMSECRETS_CURRENCY", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Choice(choices: self::SUPPORTED_CURRENCIES)] public string $currency = "EUR"; @@ -56,7 +60,8 @@ class OEMSecretsSettings * @var bool If this is enabled, distributors with zero prices * will be discarded from the creation of a new part */ - #[SettingsParameter(label: new TM("settings.ips.oemsecrets.keepZeroPrices"), description: new TM("settings.ips.oemsecrets.keepZeroPrices.help"), envVar: "bool:PROVIDER_OEMSECRETS_ZERO_PRICE")] + #[SettingsParameter(label: new TM("settings.ips.oemsecrets.keepZeroPrices"), description: new TM("settings.ips.oemsecrets.keepZeroPrices.help"), + envVar: "bool:PROVIDER_OEMSECRETS_ZERO_PRICE", envVarMode: EnvVarMode::OVERWRITE)] public bool $keepZeroPrices = false; /** @@ -64,7 +69,8 @@ class OEMSecretsSettings * # from the description transforming unstructured descriptions into structured parameters; * # each parameter in description should have the form: "...;name1:value1;name2:value2" */ - #[SettingsParameter(label: new TM("settings.ips.oemsecrets.parseParams"), description: new TM("settings.ips.oemsecrets.parseParams.help"), envVar: "bool:PROVIDER_OEMSECRETS_SET_PARAM")] + #[SettingsParameter(label: new TM("settings.ips.oemsecrets.parseParams"), description: new TM("settings.ips.oemsecrets.parseParams.help"), + envVar: "bool:PROVIDER_OEMSECRETS_SET_PARAM", envVarMode: EnvVarMode::OVERWRITE)] public bool $parseParams = true; #[SettingsParameter(label: new TM("settings.ips.oemsecrets.sortMode"), envVar: "PROVIDER_OEMSECRETS_SORT_CRITERIA", envVarMapper: [self::class, "mapSortModeEnvVar"])] diff --git a/src/Settings/InfoProviderSystem/OctopartSettings.php b/src/Settings/InfoProviderSystem/OctopartSettings.php new file mode 100644 index 00000000..1b39d87a --- /dev/null +++ b/src/Settings/InfoProviderSystem/OctopartSettings.php @@ -0,0 +1,78 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\InfoProviderSystem; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Jbtronics\SettingsBundle\Settings\SettingsTrait; +use Symfony\Component\Form\Extension\Core\Type\CountryType; +use Symfony\Component\Form\Extension\Core\Type\CurrencyType; +use Symfony\Component\Form\Extension\Core\Type\NumberType; +use Symfony\Component\Translation\TranslatableMessage as TM; +use Symfony\Component\Validator\Constraints as Assert; + +#[Settings(label: new TM("settings.ips.octopart"))] +#[SettingsIcon("fa-plug")] +class OctopartSettings +{ + use SettingsTrait; + + #[SettingsParameter( + label: new TM("settings.ips.digikey.client_id"), + envVar: "PROVIDER_OCTOPART_CLIENT_ID", envVarMode: EnvVarMode::OVERWRITE + )] + public ?string $clientId = null; + + #[SettingsParameter( + label: new TM("settings.ips.digikey.secret"), + envVar: "PROVIDER_OCTOPART_SECRET", envVarMode: EnvVarMode::OVERWRITE + )] + public ?string $secret = null; + + #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, + formOptions: ["preferred_choices" => ["EUR", "USD", "CHF", "GBP"]], + envVar: "PROVIDER_OCTOPART_CURRENCY", envVarMode: EnvVarMode::OVERWRITE)] + #[Assert\Currency()] + public string $currency = "EUR"; + + #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, + envVar: "PROVIDER_OCTOPART_COUNTRY", envVarMode: EnvVarMode::OVERWRITE)] + #[Assert\Country] + public string $country = "DE"; + + #[SettingsParameter(label: new TM("settings.ips.octopart.searchLimit"), description: new TM("settings.ips.octopart.searchLimit.help"), + formType: NumberType::class, formOptions: ["attr" => ["min" => 1, "max" => 100]], + envVar: "int:PROVIDER_OCTOPART_SEARCH_LIMIT", envVarMode: EnvVarMode::OVERWRITE)] + #[Assert\Range(min: 1, max: 100)] + public int $searchLimit = 10; + + #[SettingsParameter(label: new TM("settings.ips.octopart.onlyAuthorizedSellers"), + description: new TM("settings.ips.octopart.onlyAuthorizedSellers.help"), + envVar: "bool:PROVIDER_OCTOPART_ONLY_AUTHORIZED_SELLERS", envVarMode: EnvVarMode::OVERWRITE + )] + public bool $onlyAuthorizedSellers = true; + +} \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/PollinSettings.php b/src/Settings/InfoProviderSystem/PollinSettings.php index 8a7713c6..033d8b7e 100644 --- a/src/Settings/InfoProviderSystem/PollinSettings.php +++ b/src/Settings/InfoProviderSystem/PollinSettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Symfony\Component\Translation\TranslatableMessage as TM; @@ -32,6 +33,7 @@ use Symfony\Component\Translation\TranslatableMessage as TM; #[SettingsIcon("fa-plug")] class PollinSettings { - #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), envVar: "bool:PROVIDER_POLLIN_ENABLED")] + #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), + envVar: "bool:PROVIDER_POLLIN_ENABLED", envVarMode: EnvVarMode::OVERWRITE)] public bool $enabled = false; } \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/ReicheltSettings.php b/src/Settings/InfoProviderSystem/ReicheltSettings.php index 8672ae69..588447de 100644 --- a/src/Settings/InfoProviderSystem/ReicheltSettings.php +++ b/src/Settings/InfoProviderSystem/ReicheltSettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Jbtronics\SettingsBundle\Settings\SettingsTrait; @@ -41,22 +42,27 @@ class ReicheltSettings public const SUPPORTED_LANGUAGE = ["en", "de", "fr", "nl", "pl", "it", "es"]; - #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), envVar: "bool:PROVIDER_REICHELT_ENABLED")] + #[SettingsParameter(label: new TM("settings.ips.lcsc.enabled"), + envVar: "bool:PROVIDER_REICHELT_ENABLED", envVarMode: EnvVarMode::OVERWRITE)] public bool $enabled = false; - #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => ["EUR"]], envVar: "PROVIDER_REICHELT_CURRENCY")] + #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => ["EUR"]], + envVar: "PROVIDER_REICHELT_CURRENCY", envVarMode: EnvVarMode::OVERWRITE)] public string $currency = "EUR"; - #[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class, formOptions: ["preferred_choices" => self::SUPPORTED_LANGUAGE], envVar: "PROVIDER_REICHELT_LANGUAGE")] + #[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class, formOptions: ["preferred_choices" => self::SUPPORTED_LANGUAGE], + envVar: "PROVIDER_REICHELT_LANGUAGE", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Language()] #[Assert\Choice(choices: self::SUPPORTED_LANGUAGE)] public string $language = "en"; - #[SettingsParameter(label: new TM("settings.ips.tme.country"), envVar: "PROVIDER_REICHELT_COUNTRY", formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]])] + #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]], + envVar: "PROVIDER_REICHELT_COUNTRY", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Country] public string $country = "DE"; - #[SettingsParameter(label: new TM("settings.ips.reichelt.include_vat"), envVar: "bool:PROVIDER_REICHELT_INCLUDE_VAT")] + #[SettingsParameter(label: new TM("settings.ips.reichelt.include_vat"), + envVar: "bool:PROVIDER_REICHELT_INCLUDE_VAT", envVarMode: EnvVarMode::OVERWRITE)] public bool $includeVAT = true; } \ No newline at end of file diff --git a/src/Settings/InfoProviderSystem/TMESettings.php b/src/Settings/InfoProviderSystem/TMESettings.php index f414e984..c7b57ae7 100644 --- a/src/Settings/InfoProviderSystem/TMESettings.php +++ b/src/Settings/InfoProviderSystem/TMESettings.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace App\Settings\InfoProviderSystem; use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Jbtronics\SettingsBundle\Settings\SettingsTrait; @@ -42,24 +43,30 @@ class TMESettings private const SUPPORTED_CURRENCIES = ["EUR", "USD", "PLN", "GBP"]; #[SettingsParameter(label: new TM("settings.ips.tme.token"), - description: new TM("settings.ips.tme.token.help"), formOptions: ["help_html" => true], envVar: "PROVIDER_TME_KEY")] + description: new TM("settings.ips.tme.token.help"), formOptions: ["help_html" => true], + envVar: "PROVIDER_TME_KEY", envVarMode: EnvVarMode::OVERWRITE)] public ?string $apiToken = null; - #[SettingsParameter(label: new TM("settings.ips.tme.secret"), envVar: "PROVIDER_TME_SECRET")] + #[SettingsParameter(label: new TM("settings.ips.tme.secret"), + envVar: "PROVIDER_TME_SECRET", envVarMode: EnvVarMode::OVERWRITE)] public ?string $apiSecret = null; - #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => self::SUPPORTED_CURRENCIES], envVar: "PROVIDER_TME_CURRENCY")] + #[SettingsParameter(label: new TM("settings.ips.tme.currency"), formType: CurrencyType::class, formOptions: ["preferred_choices" => self::SUPPORTED_CURRENCIES], + envVar: "PROVIDER_TME_CURRENCY", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Choice(choices: self::SUPPORTED_CURRENCIES)] public string $currency = "EUR"; - #[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class, formOptions: ["preferred_choices" => ["en", "de", "fr", "pl"]], envVar: "PROVIDER_TME_LANGUAGE")] + #[SettingsParameter(label: new TM("settings.ips.tme.language"), formType: LanguageType::class, formOptions: ["preferred_choices" => ["en", "de", "fr", "pl"]], + envVar: "PROVIDER_TME_LANGUAGE", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Language] public string $language = "en"; - #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]], envVar: "PROVIDER_TME_COUNTRY")] + #[SettingsParameter(label: new TM("settings.ips.tme.country"), formType: CountryType::class, formOptions: ["preferred_choices" => ["DE", "PL", "GB", "FR"]], + envVar: "PROVIDER_TME_COUNTRY", envVarMode: EnvVarMode::OVERWRITE)] #[Assert\Country] public string $country = "DE"; - #[SettingsParameter(label: new TM("settings.ips.tme.grossPrices"), envVar: "bool:PROVIDER_TME_GET_GROSS_PRICES")] + #[SettingsParameter(label: new TM("settings.ips.tme.grossPrices"), + envVar: "bool:PROVIDER_TME_GET_GROSS_PRICES", envVarMode: EnvVarMode::OVERWRITE)] public bool $grossPrices = true; } \ No newline at end of file diff --git a/src/Settings/MiscSettings/ExchangeRateSettings.php b/src/Settings/MiscSettings/ExchangeRateSettings.php new file mode 100644 index 00000000..70bf15dd --- /dev/null +++ b/src/Settings/MiscSettings/ExchangeRateSettings.php @@ -0,0 +1,41 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\MiscSettings; + +use App\Settings\SettingsIcon; +use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\Settings\Settings; +use Jbtronics\SettingsBundle\Settings\SettingsParameter; +use Symfony\Component\Translation\TranslatableMessage as TM; + +#[Settings(name: "exchange_rate", label: new TM("settings.misc.exchange_rate"))] +#[SettingsIcon("fa-money-bill-transfer")] +class ExchangeRateSettings +{ + #[SettingsParameter(label: new TM("settings.misc.exchange_rate.fixer_api_key"), + description: new TM("settings.misc.exchange_rate.fixer_api_key.help"), + envVar: "FIXER_API_KEY", envVarMode: EnvVarMode::OVERWRITE, + )] + public ?string $fixerApiKey = null; +} \ No newline at end of file diff --git a/src/Settings/MiscSettings/MiscSettings.php b/src/Settings/MiscSettings/MiscSettings.php index a2ad0fd4..b8a3a73f 100644 --- a/src/Settings/MiscSettings/MiscSettings.php +++ b/src/Settings/MiscSettings/MiscSettings.php @@ -31,4 +31,7 @@ class MiscSettings { #[EmbeddedSettings] public ?KiCadEDASettings $kicadEDA = null; + + #[EmbeddedSettings] + public ?ExchangeRateSettings $exchangeRate = null; } \ No newline at end of file diff --git a/src/Settings/SystemSettings/HistorySettings.php b/src/Settings/SystemSettings/HistorySettings.php index 3602a398..46003c6d 100644 --- a/src/Settings/SystemSettings/HistorySettings.php +++ b/src/Settings/SystemSettings/HistorySettings.php @@ -70,6 +70,7 @@ class HistorySettings description: new TM("settings.system.history.enforceComments.description"), options: ['type' => EnumType::class, 'nullable' => false, 'options' => ['class' => EventCommentType::class]], formType: EnforceEventCommentTypesType::class, + formOptions: ['required' => false, "empty_data" => []], envVar: "ENFORCE_CHANGE_COMMENTS_FOR", envVarMode: EnvVarMode::OVERWRITE, envVarMapper: [self::class, 'mapEnforceComments'] )] public array $enforceComments = []; diff --git a/templates/parts/info/_picture.html.twig b/templates/parts/info/_picture.html.twig index b532f9b9..e6aa74b3 100644 --- a/templates/parts/info/_picture.html.twig +++ b/templates/parts/info/_picture.html.twig @@ -13,6 +13,7 @@
{% endfor %} diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 3ca784cd..3f0387df 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -12922,5 +12922,107 @@ Please note, that you can not impersonate a disabled user. If you try you will g