From dbb30e2a31fd600f4d1a03417f765c80b3f06177 Mon Sep 17 00:00:00 2001 From: Thomas Skerbis Date: Sun, 7 Jun 2026 19:43:51 +0200 Subject: [PATCH 1/4] =?UTF-8?q?Fix=20#88=20und=20#109,=20i18n=20erg=C3=A4n?= =?UTF-8?q?zen,=20Dependencies=20aktualisieren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Changelog.md | 5 + composer.json | 3 + composer.lock | 389 +- lang/de_de.lang | 8 + lang/en_gb.lang | 8 + lib/DateFilter.php | 97 +- package.yml | 2 +- pages/events.php | 8 +- pages/media.php | 8 +- pages/pages.php | 20 +- pages/referer.php | 6 +- update.php | 56 + vendor/autoload.php | 5 +- vendor/composer/InstalledVersions.php | 45 +- vendor/composer/autoload_files.php | 1 - vendor/composer/autoload_psr4.php | 2 - vendor/composer/autoload_static.php | 14 - vendor/composer/ca-bundle/LICENSE | 19 - vendor/composer/ca-bundle/README.md | 85 - vendor/composer/ca-bundle/composer.json | 54 - vendor/composer/ca-bundle/res/cacert.pem | 3534 ----- vendor/composer/ca-bundle/src/CaBundle.php | 431 - vendor/composer/installed.json | 392 +- vendor/composer/installed.php | 81 +- vendor/composer/platform_check.php | 5 +- .../.github/workflows/export-on-tests.yml | 37 + .../.github/workflows/php-cs-fixer.yml | 4 +- .../crawler-detect/.github/workflows/test.yml | 8 +- vendor/jaybizzle/crawler-detect/.php_cs.dist | 1 - vendor/jaybizzle/crawler-detect/README.md | 93 +- vendor/jaybizzle/crawler-detect/changes.txt | 3 + vendor/jaybizzle/crawler-detect/composer.json | 4 +- vendor/jaybizzle/crawler-detect/export.php | 4 +- .../crawler-detect/raw/Crawlers.json | 2 +- .../jaybizzle/crawler-detect/raw/Crawlers.txt | 64 +- .../crawler-detect/raw/Exclusions.json | 2 +- .../crawler-detect/raw/Exclusions.txt | 6 +- .../jaybizzle/crawler-detect/raw/Headers.json | 2 +- .../jaybizzle/crawler-detect/raw/Headers.txt | 3 +- .../crawler-detect/src/CrawlerDetect.php | 54 +- .../crawler-detect/src/Fixtures/Crawlers.php | 70 +- .../src/Fixtures/Exclusions.php | 8 +- .../crawler-detect/src/Fixtures/Headers.php | 6 +- vendor/matomo/device-detector/ClientHints.php | 80 +- .../matomo/device-detector/DeviceDetector.php | 146 +- .../device-detector/Parser/AbstractParser.php | 86 +- vendor/matomo/device-detector/Parser/Bot.php | 19 +- .../Parser/Client/AbstractClientParser.php | 43 +- .../device-detector/Parser/Client/Browser.php | 391 +- .../Parser/Client/Browser/Engine.php | 5 + .../Parser/Client/Browser/Engine/Version.php | 16 +- .../Parser/Device/AbstractDeviceParser.php | 537 +- .../device-detector/Parser/Device/HbbTv.php | 17 +- .../device-detector/Parser/Device/ShellTv.php | 9 +- .../Parser/OperatingSystem.php | 280 +- vendor/matomo/device-detector/README.md | 67 +- vendor/matomo/device-detector/Yaml/Pecl.php | 2 +- vendor/matomo/device-detector/autoload.php | 2 +- vendor/matomo/device-detector/composer.json | 12 +- vendor/matomo/device-detector/phpcs.xml | 111 - .../matomo/device-detector/regexes/bots.yml | 3023 +++- .../regexes/client/browser_engine.yml | 22 +- .../regexes/client/browsers.yml | 1733 ++- .../regexes/client/feed_readers.yml | 44 +- .../regexes/client/hints/apps.yml | 81 +- .../regexes/client/hints/browsers.yml | 137 +- .../regexes/client/libraries.yml | 350 +- .../regexes/client/mediaplayers.yml | 70 +- .../regexes/client/mobile_apps.yml | 1371 +- .../device-detector/regexes/client/pim.yml | 84 +- .../regexes/device/car_browsers.yml | 16 + .../regexes/device/consoles.yml | 27 +- .../regexes/device/mobiles.yml | 12344 ++++++++++++---- .../regexes/device/notebooks.yml | 15 +- .../regexes/device/portable_media_player.yml | 66 +- .../regexes/device/shell_tv.yml | 12 + .../regexes/device/televisions.yml | 768 +- vendor/matomo/device-detector/regexes/oss.yml | 1375 +- vendor/matomo/network/README.md | 2 +- vendor/matomo/network/composer.json | 4 +- vendor/matomo/network/src/IPUtils.php | 2 +- vendor/matomo/network/tests/IPTest.php | 293 - vendor/matomo/network/tests/IPUtilsTest.php | 343 - vendor/matomo/network/tests/IPv4Test.php | 78 - vendor/matomo/network/tests/IPv6Test.php | 141 - .../.github/pull_request_template.md | 1 + .../referrer-spam-blacklist/spammers.txt | 432 +- vendor/maxmind-db/reader/CHANGELOG.md | 24 + vendor/maxmind-db/reader/README.md | 41 +- vendor/maxmind-db/reader/autoload.php | 2 +- vendor/maxmind-db/reader/composer.json | 9 +- vendor/maxmind-db/reader/ext/maxminddb.c | 10 +- vendor/maxmind-db/reader/ext/php_maxminddb.h | 2 +- vendor/maxmind-db/reader/package.xml | 10 +- .../reader/src/MaxMind/Db/Reader.php | 51 +- .../reader/src/MaxMind/Db/Reader/Decoder.php | 17 + .../reader/src/MaxMind/Db/Reader/Metadata.php | 17 +- vendor/symfony/cache-contracts/.gitignore | 3 - .../cache-contracts/CacheInterface.php | 6 +- vendor/symfony/cache-contracts/CacheTrait.php | 4 +- vendor/symfony/cache-contracts/LICENSE | 2 +- .../symfony/cache/Adapter/AbstractAdapter.php | 2 +- vendor/symfony/cache/Adapter/ApcuAdapter.php | 2 +- vendor/symfony/cache/Adapter/ArrayAdapter.php | 2 +- vendor/symfony/cache/Adapter/ChainAdapter.php | 4 +- .../cache/Adapter/CouchbaseBucketAdapter.php | 2 +- .../Adapter/CouchbaseCollectionAdapter.php | 2 +- .../cache/Adapter/DoctrineDbalAdapter.php | 5 +- .../cache/Adapter/FilesystemAdapter.php | 2 +- .../Adapter/FilesystemTagAwareAdapter.php | 2 +- .../cache/Adapter/MemcachedAdapter.php | 4 +- vendor/symfony/cache/Adapter/NullAdapter.php | 2 +- vendor/symfony/cache/Adapter/PdoAdapter.php | 11 +- .../symfony/cache/Adapter/PhpArrayAdapter.php | 2 +- .../symfony/cache/Adapter/PhpFilesAdapter.php | 2 +- vendor/symfony/cache/Adapter/ProxyAdapter.php | 2 +- vendor/symfony/cache/Adapter/RedisAdapter.php | 2 +- .../cache/Adapter/RedisTagAwareAdapter.php | 2 +- .../symfony/cache/Adapter/TagAwareAdapter.php | 2 +- .../cache/Adapter/TraceableAdapter.php | 2 +- .../DataCollector/CacheDataCollector.php | 2 +- .../DependencyInjection/CachePoolPass.php | 6 +- vendor/symfony/cache/LockRegistry.php | 2 +- .../cache/Marshaller/DefaultMarshaller.php | 2 +- .../cache/Marshaller/SodiumMarshaller.php | 2 +- .../cache/Marshaller/TagAwareMarshaller.php | 2 +- .../Messenger/EarlyExpirationDispatcher.php | 4 +- .../cache/Traits/AbstractAdapterTrait.php | 4 + .../symfony/cache/Traits/ContractsTrait.php | 2 +- .../cache/Traits/FilesystemCommonTrait.php | 13 +- vendor/symfony/cache/Traits/RedisTrait.php | 66 +- vendor/symfony/cache/composer.json | 2 +- .../symfony/deprecation-contracts/.gitignore | 3 - .../deprecation-contracts/CHANGELOG.md | 5 - vendor/symfony/deprecation-contracts/LICENSE | 19 - .../symfony/deprecation-contracts/README.md | 26 - .../deprecation-contracts/composer.json | 35 - .../deprecation-contracts/function.php | 27 - vendor/symfony/service-contracts/.gitignore | 3 - .../service-contracts/Attribute/Required.php | 25 - .../Attribute/SubscribedService.php | 33 - vendor/symfony/service-contracts/CHANGELOG.md | 5 - vendor/symfony/service-contracts/LICENSE | 19 - vendor/symfony/service-contracts/README.md | 9 - .../service-contracts/ResetInterface.php | 30 - .../service-contracts/ServiceLocatorTrait.php | 128 - .../ServiceProviderInterface.php | 36 - .../ServiceSubscriberInterface.php | 53 - .../ServiceSubscriberTrait.php | 109 - .../Test/ServiceLocatorTest.php | 95 - .../symfony/service-contracts/composer.json | 42 - .../Exception/ClassNotFoundException.php | 2 +- .../NotInstantiableTypeException.php | 2 +- vendor/symfony/var-exporter/VarExporter.php | 2 +- 154 files changed, 19594 insertions(+), 11779 deletions(-) delete mode 100644 vendor/composer/ca-bundle/LICENSE delete mode 100644 vendor/composer/ca-bundle/README.md delete mode 100644 vendor/composer/ca-bundle/composer.json delete mode 100644 vendor/composer/ca-bundle/res/cacert.pem delete mode 100644 vendor/composer/ca-bundle/src/CaBundle.php create mode 100644 vendor/jaybizzle/crawler-detect/.github/workflows/export-on-tests.yml create mode 100644 vendor/jaybizzle/crawler-detect/changes.txt delete mode 100644 vendor/matomo/device-detector/phpcs.xml delete mode 100644 vendor/matomo/network/tests/IPTest.php delete mode 100644 vendor/matomo/network/tests/IPUtilsTest.php delete mode 100644 vendor/matomo/network/tests/IPv4Test.php delete mode 100644 vendor/matomo/network/tests/IPv6Test.php create mode 100644 vendor/matomo/referrer-spam-blacklist/.github/pull_request_template.md delete mode 100644 vendor/symfony/cache-contracts/.gitignore delete mode 100644 vendor/symfony/deprecation-contracts/.gitignore delete mode 100644 vendor/symfony/deprecation-contracts/CHANGELOG.md delete mode 100644 vendor/symfony/deprecation-contracts/LICENSE delete mode 100644 vendor/symfony/deprecation-contracts/README.md delete mode 100644 vendor/symfony/deprecation-contracts/composer.json delete mode 100644 vendor/symfony/deprecation-contracts/function.php delete mode 100644 vendor/symfony/service-contracts/.gitignore delete mode 100644 vendor/symfony/service-contracts/Attribute/Required.php delete mode 100644 vendor/symfony/service-contracts/Attribute/SubscribedService.php delete mode 100644 vendor/symfony/service-contracts/CHANGELOG.md delete mode 100644 vendor/symfony/service-contracts/LICENSE delete mode 100644 vendor/symfony/service-contracts/README.md delete mode 100644 vendor/symfony/service-contracts/ResetInterface.php delete mode 100644 vendor/symfony/service-contracts/ServiceLocatorTrait.php delete mode 100644 vendor/symfony/service-contracts/ServiceProviderInterface.php delete mode 100644 vendor/symfony/service-contracts/ServiceSubscriberInterface.php delete mode 100644 vendor/symfony/service-contracts/ServiceSubscriberTrait.php delete mode 100644 vendor/symfony/service-contracts/Test/ServiceLocatorTest.php delete mode 100644 vendor/symfony/service-contracts/composer.json diff --git a/Changelog.md b/Changelog.md index c79f4db..a136f45 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,10 @@ # Changelog +## [3.2.1] - 07.06.2026 + +- Datumsbereich bleibt beim Wechsel zwischen Statistik-Tabs erhalten ([#88](https://github.com/FriendsOfREDAXO/statistics/issues/88)) +- Weitere harte UI-Texte in Sprachdateien ausgelagert ([#109](https://github.com/FriendsOfREDAXO/statistics/issues/109)) + ## [3.2.0] - 29.03.2026 - Performance improvements with lazy loading diff --git a/composer.json b/composer.json index 9e76b65..14fa80c 100644 --- a/composer.json +++ b/composer.json @@ -8,10 +8,13 @@ "matomo/network": "^2.0" }, "replace": { + "composer/ca-bundle": "*", "psr/log": "*", "psr/container": "*", "psr/http-message": "*", "ankitpokhrel/tus-php": "*", + "symfony/deprecation-contracts": "*", + "symfony/service-contracts": "*", "symfony/polyfill-ctype": "*", "symfony/polyfill-iconv": "*", "symfony/polyfill-intl-grapheme": "*", diff --git a/composer.lock b/composer.lock index d35ee84..87450cd 100644 --- a/composer.lock +++ b/composer.lock @@ -4,90 +4,14 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "621c6fea5cc8098f46adc636ce82d464", + "content-hash": "aa9b3fc6f9a2d32cca0119af477ff995", "packages": [ - { - "name": "composer/ca-bundle", - "version": "1.4.0", - "source": { - "type": "git", - "url": "https://github.com/composer/ca-bundle.git", - "reference": "b66d11b7479109ab547f9405b97205640b17d385" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/b66d11b7479109ab547f9405b97205640b17d385", - "reference": "b66d11b7479109ab547f9405b97205640b17d385", - "shasum": "" - }, - "require": { - "ext-openssl": "*", - "ext-pcre": "*", - "php": "^5.3.2 || ^7.0 || ^8.0" - }, - "require-dev": { - "phpstan/phpstan": "^0.12.55", - "psr/log": "^1.0", - "symfony/phpunit-bridge": "^4.2 || ^5", - "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\CaBundle\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - } - ], - "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", - "keywords": [ - "cabundle", - "cacert", - "certificate", - "ssl", - "tls" - ], - "support": { - "irc": "irc://irc.freenode.org/composer", - "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.4.0" - }, - "funding": [ - { - "url": "https://packagist.com", - "type": "custom" - }, - { - "url": "https://github.com/composer", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" - } - ], - "time": "2023-12-18T12:05:55+00:00" - }, { "name": "geoip2/geoip2", "version": "v2.13.0", "source": { "type": "git", - "url": "git@github.com:maxmind/GeoIP2-php.git", + "url": "https://github.com/maxmind/GeoIP2-php.git", "reference": "6a41d8fbd6b90052bc34dff3b4252d0f88067b23" }, "dist": { @@ -134,27 +58,31 @@ "geolocation", "maxmind" ], + "support": { + "issues": "https://github.com/maxmind/GeoIP2-php/issues", + "source": "https://github.com/maxmind/GeoIP2-php/tree/v2.13.0" + }, "time": "2022-08-05T20:32:58+00:00" }, { "name": "jaybizzle/crawler-detect", - "version": "v1.2.116", + "version": "v1.3.11", "source": { "type": "git", "url": "https://github.com/JayBizzle/Crawler-Detect.git", - "reference": "97e9fe30219e60092e107651abb379a38b342921" + "reference": "484792759de89fe94ea6a192065ea7cd99f1eaa2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/97e9fe30219e60092e107651abb379a38b342921", - "reference": "97e9fe30219e60092e107651abb379a38b342921", + "url": "https://api.github.com/repos/JayBizzle/Crawler-Detect/zipball/484792759de89fe94ea6a192065ea7cd99f1eaa2", + "reference": "484792759de89fe94ea6a192065ea7cd99f1eaa2", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.1.0" }, "require-dev": { - "phpunit/phpunit": "^4.8|^5.5|^6.5|^9.4" + "phpunit/phpunit": "^4.8|^5.5|^6.5|^7.5|^8.5.52|^9.4" }, "type": "library", "autoload": { @@ -184,22 +112,22 @@ ], "support": { "issues": "https://github.com/JayBizzle/Crawler-Detect/issues", - "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.2.116" + "source": "https://github.com/JayBizzle/Crawler-Detect/tree/v1.3.11" }, - "time": "2023-07-21T15:49:49+00:00" + "time": "2026-05-10T14:08:06+00:00" }, { "name": "matomo/device-detector", - "version": "6.2.1", + "version": "6.5.1", "source": { "type": "git", "url": "https://github.com/matomo-org/device-detector.git", - "reference": "19138b0c4b9ddf4ffd8e423d6af3764b7317cb0b" + "reference": "f30457500c6be4c80c8830466f8a746724779fd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/19138b0c4b9ddf4ffd8e423d6af3764b7317cb0b", - "reference": "19138b0c4b9ddf4ffd8e423d6af3764b7317cb0b", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/f30457500c6be4c80c8830466f8a746724779fd0", + "reference": "f30457500c6be4c80c8830466f8a746724779fd0", "shasum": "" }, "require": { @@ -213,13 +141,13 @@ "matthiasmullie/scrapbook": "^1.4.7", "mayflower/mo4-coding-standard": "^v9.0.0", "phpstan/phpstan": "^1.10.44", - "phpunit/phpunit": "^8.5.8", - "psr/cache": "^1.0.1", - "psr/simple-cache": "^1.0.1", - "symfony/yaml": "^5.1.7" + "phpunit/phpunit": "^8.5.2 || ^9 || ^10 || ^11 || ^12 || ^13", + "psr/cache": "^1.0.1 || ^2.0 || ^3.0", + "psr/simple-cache": "^1.0.1 || ^2.0 || ^3.0", + "slevomat/coding-standard": "<8.16.0", + "symfony/yaml": "^5.4 || ^6.4 || ^7.4 || ^8.0" }, "suggest": { - "doctrine/cache": "Can directly be used for caching purpose", "ext-yaml": "Necessary for using the Pecl YAML parser" }, "type": "library", @@ -253,29 +181,29 @@ "forum": "https://forum.matomo.org/", "issues": "https://github.com/matomo-org/device-detector/issues", "source": "https://github.com/matomo-org/matomo", - "wiki": "https://dev.matomo.org/" + "wiki": "https://developer.matomo.org/" }, - "time": "2024-01-05T09:03:21+00:00" + "time": "2026-05-27T09:53:26+00:00" }, { "name": "matomo/network", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/matomo-org/component-network.git", - "reference": "ff654b8fc7778b80279815d06a368f7b41249501" + "reference": "49407377fb4755cb1eb987ca827951bed732374e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/component-network/zipball/ff654b8fc7778b80279815d06a368f7b41249501", - "reference": "ff654b8fc7778b80279815d06a368f7b41249501", + "url": "https://api.github.com/repos/matomo-org/component-network/zipball/49407377fb4755cb1eb987ca827951bed732374e", + "reference": "49407377fb4755cb1eb987ca827951bed732374e", "shasum": "" }, "require": { - "php": ">=5.4" + "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^4.8.36" + "phpunit/phpunit": "^8 || ^9 || ^10 || ^11 || ^12" }, "type": "library", "autoload": { @@ -289,22 +217,22 @@ ], "support": { "issues": "https://github.com/matomo-org/component-network/issues", - "source": "https://github.com/matomo-org/component-network/tree/2.0.1" + "source": "https://github.com/matomo-org/component-network/tree/2.0.3" }, - "time": "2020-10-05T06:09:39+00:00" + "time": "2026-04-17T10:12:27+00:00" }, { "name": "matomo/referrer-spam-blacklist", - "version": "4.0.0", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/matomo-org/referrer-spam-list.git", - "reference": "afe4c1ea107ee7a8915a0d5eb0031cf0366608a8" + "reference": "e3254bf771f6520aa9701276a74c5a19df535d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/referrer-spam-list/zipball/afe4c1ea107ee7a8915a0d5eb0031cf0366608a8", - "reference": "afe4c1ea107ee7a8915a0d5eb0031cf0366608a8", + "url": "https://api.github.com/repos/matomo-org/referrer-spam-list/zipball/e3254bf771f6520aa9701276a74c5a19df535d4a", + "reference": "e3254bf771f6520aa9701276a74c5a19df535d4a", "shasum": "" }, "replace": { @@ -318,42 +246,41 @@ "description": "Community-contributed list of referrer spammers", "support": { "issues": "https://github.com/matomo-org/referrer-spam-list/issues", - "source": "https://github.com/matomo-org/referrer-spam-list/tree/4.0.0" + "source": "https://github.com/matomo-org/referrer-spam-list/tree/4.0.5" }, - "time": "2020-08-10T19:54:07+00:00" + "time": "2026-04-15T22:44:28+00:00" }, { "name": "maxmind-db/reader", - "version": "v1.11.1", + "version": "v1.13.1", "source": { "type": "git", - "url": "git@github.com:maxmind/MaxMind-DB-Reader-php.git", - "reference": "1e66f73ffcf25e17c7a910a1317e9720a95497c7" + "url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git", + "reference": "2194f58d0f024ce923e685cdf92af3daf9951908" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/1e66f73ffcf25e17c7a910a1317e9720a95497c7", - "reference": "1e66f73ffcf25e17c7a910a1317e9720a95497c7", + "url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/2194f58d0f024ce923e685cdf92af3daf9951908", + "reference": "2194f58d0f024ce923e685cdf92af3daf9951908", "shasum": "" }, "require": { "php": ">=7.2" }, "conflict": { - "ext-maxminddb": "<1.11.1,>=2.0.0" + "ext-maxminddb": "<1.11.1 || >=2.0.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "3.*", - "php-coveralls/php-coveralls": "^2.1", "phpstan/phpstan": "*", - "phpunit/phpcov": ">=6.0.0", "phpunit/phpunit": ">=8.0.0,<10.0.0", - "squizlabs/php_codesniffer": "3.*" + "squizlabs/php_codesniffer": "4.*" }, "suggest": { "ext-bcmath": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", "ext-gmp": "bcmath or gmp is required for decoding larger integers with the pure PHP decoder", - "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups" + "ext-maxminddb": "A C-based database decoder that provides significantly faster lookups", + "maxmind-db/reader-ext": "C extension for significantly faster IP lookups (install via PIE: pie install maxmind-db/reader-ext)" }, "type": "library", "autoload": { @@ -381,7 +308,11 @@ "geolocation", "maxmind" ], - "time": "2023-12-02T00:09:23+00:00" + "support": { + "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.13.1" + }, + "time": "2025-11-21T22:24:26+00:00" }, { "name": "maxmind/web-service-common", @@ -439,7 +370,7 @@ "version": "0.6.3", "source": { "type": "git", - "url": "git@github.com:mustangostang/spyc.git", + "url": "https://github.com/mustangostang/spyc.git", "reference": "4627c838b16550b666d15aeae1e5289dd5b77da0" }, "dist": { @@ -482,6 +413,10 @@ "yaml", "yml" ], + "support": { + "issues": "https://github.com/mustangostang/spyc/issues", + "source": "https://github.com/mustangostang/spyc/tree/0.6.3" + }, "time": "2019-09-10T13:16:29+00:00" }, { @@ -535,16 +470,16 @@ }, { "name": "symfony/cache", - "version": "v5.4.34", + "version": "v5.4.53", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "b17f28169f7a2f2c0cddf2b044d729f5b75efe5a" + "reference": "bf581474737420d5c932ae80b868e253f465ee5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/b17f28169f7a2f2c0cddf2b044d729f5b75efe5a", - "reference": "b17f28169f7a2f2c0cddf2b044d729f5b75efe5a", + "url": "https://api.github.com/repos/symfony/cache/zipball/bf581474737420d5c932ae80b868e253f465ee5b", + "reference": "bf581474737420d5c932ae80b868e253f465ee5b", "shasum": "" }, "require": { @@ -573,7 +508,7 @@ "cache/integration-tests": "dev-master", "doctrine/cache": "^1.6|^2.0", "doctrine/dbal": "^2.13.1|^3|^4", - "predis/predis": "^1.1", + "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/dependency-injection": "^4.4|^5.0|^6.0", @@ -612,7 +547,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v5.4.34" + "source": "https://github.com/symfony/cache/tree/v5.4.53" }, "funding": [ { @@ -623,25 +558,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2023-12-18T14:56:06+00:00" + "time": "2026-05-24T08:41:21+00:00" }, { "name": "symfony/cache-contracts", - "version": "v2.5.2", + "version": "v2.5.4", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc" + "reference": "517c3a3619dadfa6952c4651767fcadffb4df65e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", - "reference": "64be4a7acb83b6f2bf6de9a02cee6dad41277ebc", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/517c3a3619dadfa6952c4651767fcadffb4df65e", + "reference": "517c3a3619dadfa6952c4651767fcadffb4df65e", "shasum": "" }, "require": { @@ -653,167 +592,17 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Cache\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to caching", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/deprecation-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "2.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "files": [ - "function.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "A generic function and convention to trigger deprecation notices", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-01-02T09:53:40+00:00" - }, - { - "name": "symfony/service-contracts", - "version": "v2.5.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", - "shasum": "" - }, - "require": { - "php": ">=7.2.5", - "psr/container": "^1.1", - "symfony/deprecation-contracts": "^2.1|^3" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "suggest": { - "symfony/service-implementation": "" - }, - "type": "library", - "extra": { "branch-alias": { "dev-main": "2.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\Service\\": "" + "Symfony\\Contracts\\Cache\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -830,7 +619,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Generic abstractions related to writing services", + "description": "Generic abstractions related to caching", "homepage": "https://symfony.com", "keywords": [ "abstractions", @@ -841,7 +630,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" + "source": "https://github.com/symfony/cache-contracts/tree/v2.5.4" }, "funding": [ { @@ -857,20 +646,20 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:29+00:00" + "time": "2024-09-25T14:11:13+00:00" }, { "name": "symfony/var-exporter", - "version": "v5.4.32", + "version": "v5.4.45", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "fdb022f0d3d41df240c18e2eb9a117c430f06add" + "reference": "862700068db0ddfd8c5b850671e029a90246ec75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/fdb022f0d3d41df240c18e2eb9a117c430f06add", - "reference": "fdb022f0d3d41df240c18e2eb9a117c430f06add", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/862700068db0ddfd8c5b850671e029a90246ec75", + "reference": "862700068db0ddfd8c5b850671e029a90246ec75", "shasum": "" }, "require": { @@ -914,7 +703,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v5.4.32" + "source": "https://github.com/symfony/var-exporter/tree/v5.4.45" }, "funding": [ { @@ -930,19 +719,19 @@ "type": "tidelift" } ], - "time": "2023-11-16T19:33:05+00:00" + "time": "2024-09-25T14:11:13+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [], + "platform": {}, + "platform-dev": {}, "platform-overrides": { "php": "7.4" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/lang/de_de.lang b/lang/de_de.lang index b0614b4..fa4b16a 100644 --- a/lang/de_de.lang +++ b/lang/de_de.lang @@ -88,6 +88,14 @@ statistics_scroll_panel = Container statistics_scroll_none = Keines von beidem statistics_statistics_ignore_url_params = Ignoriere URL-Parameter statistics_statistics_ignore_url_params_note = URL-Parameter werden in der Statistik nicht geloggt. Z.b. www.example.com?data=1 wird als www.example.com gespeichert. +statistics_details_for = Details für: +statistics_all_domains = Alle Domains +statistics_filter_all = Alle +statistics_filter_only_200 = Nur 200er +statistics_filter_only_not_200 = Nur nicht 200er +statistics_ignore_success = Es wurden %s Einträge gelöscht. +statistics_ignore_url_future = Die URL %s wird zukünftig ignoriert. +statistics_deleted_campaign_entries = Es wurden %s Einträge der Kampagne %s gelöscht. perm_general_statistics[] = Benutzer darf das Addon "Statistiken" aufrufen. perm_options_statistics[settings] = Benutzer darf Einstellungen des Addons "Statistiken" ändern. statistics_default_datefilter_range = Standard Datumsbereich diff --git a/lang/en_gb.lang b/lang/en_gb.lang index 8ade558..639c8ab 100644 --- a/lang/en_gb.lang +++ b/lang/en_gb.lang @@ -90,6 +90,14 @@ statistics_scroll_panel = Container statistics_scroll_none = None of both statistics_statistics_ignore_url_params = Ignore URL parameters. statistics_statistics_ignore_url_params_note = URL parameters are not logged in the statistics. E.g. www.example.com?data=1 is stored as www.example.com. +statistics_details_for = Details for: +statistics_all_domains = All domains +statistics_filter_all = All +statistics_filter_only_200 = Only 200 +statistics_filter_only_not_200 = Only non-200 +statistics_ignore_success = %s entries were deleted. +statistics_ignore_url_future = The URL %s will be ignored in the future. +statistics_deleted_campaign_entries = %s entries of campaign %s were deleted. perm_general_statistics[] = User may open the "Statistics" addon. perm_options_statistics[settings] = User may change settings of the "Statistics" addon. statistics_default_datefilter_range = Default date range. diff --git a/lib/DateFilter.php b/lib/DateFilter.php index 8c0b4ec..de5b0ab 100644 --- a/lib/DateFilter.php +++ b/lib/DateFilter.php @@ -4,6 +4,8 @@ use rex; use rex_addon; +use rex_addon_interface; +use rex_request; use rex_sql; use rex_view; use InvalidArgumentException; @@ -22,8 +24,10 @@ class DateFilter public DateTimeImmutable $whole_time_start; + /** @var non-empty-string */ private string $table; - private rex_addon $addon; + private rex_addon_interface $addon; + private const SESSION_KEY = 'statistics_datefilter'; /** @@ -38,37 +42,62 @@ class DateFilter */ function __construct(string $date_start, string $date_end, string $table) { + if ('' === $table) { + throw new InvalidArgumentException('Table name must not be empty.'); + } + + /** @var non-empty-string $table */ $this->table = $table; $this->addon = rex_addon::get('statistics'); - if ($date_start == '') { - - // prefered date range - $date_range = $this->addon->getConfig('statistics_default_datefilter_range'); - - if ($date_range == 'last7days') { - $date = new DateTimeImmutable(); - $date = $date->modify("-7 day"); - $this->date_start = $date; - } elseif ($date_range == 'last30days') { - $date = new DateTimeImmutable(); - $date = $date->modify("-30 day"); - $this->date_start = $date; - } elseif ($date_range == 'thisYear') { - $date = new DateTimeImmutable(); - $date = $date->modify("-365 day"); - $this->date_start = $date; - } else { - $this->date_start = $this->getMinDateFromTable(); - } - // design decision, uncomment this line to default show only timespan where data was collected - // $this->date_end = $this->getMaxDateFromTable(); + $hasRequestDateRange = '' !== $date_start && '' !== $date_end; - $this->date_end = new DateTimeImmutable(); - // $this->date_end->modify('+1 day'); - } else { + if ($hasRequestDateRange) { $this->date_start = new DateTimeImmutable($date_start); $this->date_end = new DateTimeImmutable($date_end); + + rex_request::setSession(self::SESSION_KEY, [ + 'date_start' => $this->date_start->format('Y-m-d'), + 'date_end' => $this->date_end->format('Y-m-d'), + ]); + } else { + $sessionDateRange = rex_request::session(self::SESSION_KEY); + $hasSessionDateRange = is_array($sessionDateRange) + && isset($sessionDateRange['date_start'], $sessionDateRange['date_end']) + && is_string($sessionDateRange['date_start']) + && is_string($sessionDateRange['date_end']) + && '' !== $sessionDateRange['date_start'] + && '' !== $sessionDateRange['date_end']; + + if ($hasSessionDateRange) { + $this->date_start = new DateTimeImmutable($sessionDateRange['date_start']); + $this->date_end = new DateTimeImmutable($sessionDateRange['date_end']); + } else { + + // prefered date range + $date_range = $this->addon->getConfig('statistics_default_datefilter_range'); + + if ($date_range === 'last7days') { + $date = new DateTimeImmutable(); + $date = $date->modify('-7 day'); + $this->date_start = $date; + } elseif ($date_range === 'last30days') { + $date = new DateTimeImmutable(); + $date = $date->modify('-30 day'); + $this->date_start = $date; + } elseif ($date_range === 'thisYear') { + $date = new DateTimeImmutable(); + $date = $date->modify('-365 day'); + $this->date_start = $date; + } else { + $this->date_start = $this->getMinDateFromTable(); + } + // design decision, uncomment this line to default show only timespan where data was collected + // $this->date_end = $this->getMaxDateFromTable(); + + $this->date_end = new DateTimeImmutable(); + // $this->date_end->modify('+1 day'); + } } // set total time range to use in datefilter fragment with javascript @@ -90,16 +119,18 @@ function __construct(string $date_start, string $date_end, string $table) private function getMinDateFromTable(): DateTimeImmutable { $sql = rex_sql::factory(); - $min_date = $sql->setQuery('SELECT MIN(date) AS "date" from ' . rex::getTable($this->table)); - $min_date = $min_date->getValue('date'); + $result = $sql->setQuery('SELECT MIN(date) AS "date" from ' . rex::getTable($this->table)); + $minDateRaw = $result->getValue('date'); - if ($min_date === null) { - $min_date = new DateTimeImmutable("now"); - } else { - $min_date = DateTimeImmutable::createFromFormat('Y-m-d', $min_date); + if (!is_string($minDateRaw) || '' === $minDateRaw) { + return new DateTimeImmutable('now'); } + $minDate = DateTimeImmutable::createFromFormat('Y-m-d', $minDateRaw); + if (false === $minDate) { + return new DateTimeImmutable('now'); + } - return $min_date; + return $minDate; } } diff --git a/package.yml b/package.yml index 93547c4..5003a38 100644 --- a/package.yml +++ b/package.yml @@ -1,5 +1,5 @@ package: statistics -version: 3.2.0 +version: 3.2.1 author: Andreas Lenhardt supportpage: https://github.com/AndiLeni/statistics diff --git a/pages/events.php b/pages/events.php index 7fc2b37..ffa65d6 100644 --- a/pages/events.php +++ b/pages/events.php @@ -19,14 +19,14 @@ echo StatsSubpageRenderer::renderFilter($current_backend_page, $filter_date_helper); -if ($request_name != '' && $delete_entry === true) { +if ($request_name !== '' && $delete_entry === true) { $sql = rex_sql::factory(); $sql->setQuery('delete from ' . rex::getTable('pagestats_api') . ' where name = :name', ['name' => $request_name]); - echo rex_view::success('Es wurden ' . $sql->getRows() . ' Einträge der Kampagne ' . $request_name . ' gelöscht.'); + echo rex_view::success(sprintf($addon->i18n('statistics_deleted_campaign_entries'), (string) $sql->getRows(), htmlspecialchars($request_name, ENT_QUOTES))); } // details section -if ($request_name != '' && !$delete_entry) { +if ($request_name !== '' && !$delete_entry) { // details section for single campaign $pagedetails = new EventDetails($request_name, $filter_date_helper); @@ -36,7 +36,7 @@ $content = '
'; echo StatsSubpageRenderer::renderInfoSection( - 'Details für:', + $addon->i18n('statistics_details_for'), $request_name, $content . StatsChartConfig::renderScript('chart_details', StatsChartConfig::buildTimelineOption($sum_data['labels'], $sum_data['values'])) ); diff --git a/pages/media.php b/pages/media.php index 680957b..0950f2b 100644 --- a/pages/media.php +++ b/pages/media.php @@ -18,14 +18,14 @@ $filter_date_helper = new DateFilter($request_date_start, $request_date_end, 'pagestats_media'); echo StatsSubpageRenderer::renderFilter($current_backend_page, $filter_date_helper); -if ($request_url != '' && $delete_entry === true) { +if ($request_url !== '' && $delete_entry === true) { $sql = rex_sql::factory(); $sql->setQuery('delete from ' . rex::getTable('pagestats_media') . ' where url = :url', ['url' => $request_url]); - echo rex_view::success('Es wurden ' . $sql->getRows() . ' Einträge der Kampagne ' . $request_url . ' gelöscht.'); + echo rex_view::success(sprintf($addon->i18n('statistics_deleted_campaign_entries'), (string) $sql->getRows(), htmlspecialchars($request_url, ENT_QUOTES))); } // details section -if ($request_url != '' && !$delete_entry) { +if ($request_url !== '' && !$delete_entry) { // details section for single campaign $pagedetails = new MediaDetails($request_url, $filter_date_helper); @@ -34,7 +34,7 @@ $content = '
'; echo StatsSubpageRenderer::renderInfoSection( - 'Details für:', + $addon->i18n('statistics_details_for'), $request_url, $content . StatsChartConfig::renderScript('chart_details', StatsChartConfig::buildTimelineOption($sum_data['labels'], $sum_data['values'])) ); diff --git a/pages/pages.php b/pages/pages.php index f72ef2d..e8c6c6c 100644 --- a/pages/pages.php +++ b/pages/pages.php @@ -29,14 +29,18 @@ // check if request is for ignoring a url // if yes, add url to addon settings and delete all database entries of this url -if ($request_url != '' && $ignore_page === true) { +if ($request_url !== '' && $ignore_page === true) { $rows = $pages_helper->ignorePage($request_url); - echo rex_view::success('Es wurden ' . $rows . ' Einträge gelöscht. Die Url ' . $request_url . ' wird zukünftig ignoriert.'); + echo rex_view::success( + sprintf($addon->i18n('statistics_ignore_success'), (string) $rows) + . ' ' + . sprintf($addon->i18n('statistics_ignore_url_future'), htmlspecialchars($request_url, ENT_QUOTES)) + ); } // details for one url requested -if ($request_url != '' && !$ignore_page) { +if ($request_url !== '' && !$ignore_page) { // details section for single page $pagedetails = new PageDetails($request_url, $filter_date_helper); @@ -47,7 +51,7 @@ $content .= StatsChartConfig::renderScript('chart_details', StatsChartConfig::buildTimelineOption($sum_data['labels'], $sum_data['values'])); $content .= $pagedetails->getList(); - echo StatsSubpageRenderer::renderInfoSection('Details für:', $request_url, $content); + echo StatsSubpageRenderer::renderInfoSection($addon->i18n('statistics_details_for'), $request_url, $content); } @@ -56,7 +60,7 @@ $domains = $sql->getArray('SELECT distinct domain FROM ' . rex::getTable('pagestats_visits_per_day')); $domain_select = '