From 3cb0a55cf58f80620e007f2766f56f9595d3b4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 22 May 2026 10:57:45 +0300 Subject: [PATCH 1/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20Symfony=207?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index fa880d5..22e9daf 100644 --- a/composer.json +++ b/composer.json @@ -9,34 +9,34 @@ }], "require": { "php": ">=7.4", - "symfony/framework-bundle" : "^4.0|^5.0|^6.0", - "symfony/yaml": "^4.0|^5.0|^6.0" + "symfony/framework-bundle" : "^4.0|^5.0|^6.0|^7.0", + "symfony/yaml": "^4.0|^5.0|^6.0|^7.0" }, "require-dev": { "doctrine/dbal": "^2|^3|^4", "nyholm/symfony-bundle-test": "^2.0", "phpunit/phpunit": "^8.5|^9.5", - "symfony/phpunit-bridge": "^5.0|^6.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/event-dispatcher": "^4.4|^5.0|^6.0", - "symfony/error-handler": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", + "symfony/phpunit-bridge": "^5.0|^6.0|^7.0", + "symfony/config": "^4.4|^5.0|^6.0|^7.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0|^7.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0|^7.0", + "symfony/error-handler": "^4.4|^5.0|^6.0|^7.0", + "symfony/http-kernel": "^4.4|^5.0|^6.0|^7.0", + "symfony/http-foundation": "^4.4|^5.0|^6.0|^7.0", "symfony/deprecation-contracts": "^1.1|^2.0|^3", "symfony/event-dispatcher-contracts": "^1.1|^2.0|^3", - "symfony/routing": "^4.4|^5.0|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/filesystem": "^4.4|^5.0|^6.0", - "symfony/templating": "^4.4|^5.0|^6.0", + "symfony/routing": "^4.4|^5.0|^6.0|^7.0", + "symfony/finder": "^4.4|^5.0|^6.0|^7.0", + "symfony/filesystem": "^4.4|^5.0|^6.0|^7.0", + "symfony/templating": "^4.4|^5.0|^6.0|^7.0", "symfony/translation-contracts": "^1.1|^2.0", - "symfony/var-exporter": "^4.4|^5.0|^6.0", - "symfony/var-dumper": "^4.4|^5.0|^6.0", + "symfony/var-exporter": "^4.4|^5.0|^6.0|^7.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0|^7.0", "psr/log": "~1.0|^2|^3", "friendsofphp/php-cs-fixer": "3.4", "twig/twig": "^v2.14 || ^3.0", - "symfony/twig-bundle": "^4.4|^5.0|^6.0", - "symfony/twig-bridge": "^4.4|^5.0|^6.0", + "symfony/twig-bundle": "^4.4|^5.0|^6.0|^7.0", + "symfony/twig-bridge": "^4.4|^5.0|^6.0|^7.0", "phpstan/phpstan": "^1.10" }, "autoload": { From add185859b801042c1ea413b5db607e44722c7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 22 May 2026 11:44:46 +0300 Subject: [PATCH 2/8] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B8=20=D0=BB=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 22e9daf..e40e8c1 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ }, "require-dev": { "doctrine/dbal": "^2|^3|^4", - "nyholm/symfony-bundle-test": "^2.0", + "nyholm/symfony-bundle-test": "^3.1", "phpunit/phpunit": "^8.5|^9.5", "symfony/phpunit-bridge": "^5.0|^6.0|^7.0", "symfony/config": "^4.4|^5.0|^6.0|^7.0", @@ -33,7 +33,7 @@ "symfony/var-exporter": "^4.4|^5.0|^6.0|^7.0", "symfony/var-dumper": "^4.4|^5.0|^6.0|^7.0", "psr/log": "~1.0|^2|^3", - "friendsofphp/php-cs-fixer": "3.4", + "friendsofphp/php-cs-fixer": "^3.95", "twig/twig": "^v2.14 || ^3.0", "symfony/twig-bundle": "^4.4|^5.0|^6.0|^7.0", "symfony/twig-bridge": "^4.4|^5.0|^6.0|^7.0", From 70655564dadebdef9442849cb8ab2c92c172e9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 22 May 2026 12:11:30 +0300 Subject: [PATCH 3/8] =?UTF-8?q?PHP=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=B4=D0=BE=208.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e40e8c1..a79e5d1 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "name" : "Ilyas Salikhov" }], "require": { - "php": ">=7.4", + "php": ">=8.2", "symfony/framework-bundle" : "^4.0|^5.0|^6.0|^7.0", "symfony/yaml": "^4.0|^5.0|^6.0|^7.0" }, From 58f3650f3bc786271ad2376d486013e4c4b7af04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 22 May 2026 12:22:37 +0300 Subject: [PATCH 4/8] =?UTF-8?q?PHP=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=B4=D0=BE=208.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b45b1b1..f144651 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: build: context: . args: - PHP_IMAGE_TAG: ${PHP_IMAGE_TAG:-7.4} + PHP_IMAGE_TAG: ${PHP_IMAGE_TAG:-8.2} environment: - REDIS_HOST=redis volumes: From f45219c556671af6f7a436a2ac946bf040882824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 22 May 2026 13:12:22 +0300 Subject: [PATCH 5/8] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20CI=20=D0=BF=D0=BE=D0=B4=20php=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1dbea39..9ce56fa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,25 +19,23 @@ jobs: fail-fast: false matrix: php-version: - - '7.4' - - '8.0' - - '8.1' - '8.2' + - '8.3' + - '8.4' symfony-version: - - '4.4.*' - - '5.4.*' - - '6.2.*' + - '6.4.*' + - '7.0.*' + - '7.4.*' exclude: - php-version: '8.2' symfony-version: '4.4.*' - php-version: '8.2' symfony-version: '5.4.*' - - php-version: '8.1' - symfony-version: '4.4.*' - - php-version: '8.0' - symfony-version: '6.2.*' - - php-version: '7.4' - symfony-version: '6.2.*' + include: + - php-version: '8.2' + symfony-version: '6.4.*' + - php-version: '8.2' + symfony-version: '7.0.*' coverage: [ 'none' ] steps: - name: "Checkout" @@ -66,9 +64,9 @@ jobs: fail-fast: false matrix: php-version: - - '7.4' - - '8.0' - - '8.1' + - '8.2' + - '8.3' + - '8.4' steps: - name: "Checkout" uses: "actions/checkout@v2" From 68d7bbf73e40f5d6f72e8c1986fdb378ea0795f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Fri, 22 May 2026 15:04:15 +0300 Subject: [PATCH 6/8] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20CI=20=D0=BF=D0=BE=D0=B4=20php=208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ce56fa..eae3693 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,18 +24,7 @@ jobs: - '8.4' symfony-version: - '6.4.*' - - '7.0.*' - '7.4.*' - exclude: - - php-version: '8.2' - symfony-version: '4.4.*' - - php-version: '8.2' - symfony-version: '5.4.*' - include: - - php-version: '8.2' - symfony-version: '6.4.*' - - php-version: '8.2' - symfony-version: '7.0.*' coverage: [ 'none' ] steps: - name: "Checkout" From 7b41c8d4fc8c7cc67530c938629eeb3ce9fc71dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Thu, 28 May 2026 10:24:21 +0300 Subject: [PATCH 7/8] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA?= =?UTF-8?q?=D0=B0=20legacy=20=D0=B4=D0=BB=D1=8F=20php=207=20=D0=B8=20symfo?= =?UTF-8?q?ny=204,=205,=206.=20redis=20=D1=80=D0=B0=D0=B7=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=B0=20legacy=20=D0=B8=20=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=D1=8B=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 64 +++++- .php-cs-fixer.dist.php | 5 + Cache/Redis.php | 227 +------------------ Cache/RedisLegacy.php | 89 ++++++++ Cache/RedisPhp8.php | 89 ++++++++ Cache/RedisStopwatchTrait.php | 68 ++++++ DependencyInjection/Configuration.php | 3 - DependencyInjection/IntaroPinbaExtension.php | 3 - Logger/DbalLogger.php | 10 +- Stopwatch/Stopwatch.php | 3 +- Twig/TimedTwigEngine.php | 3 - Twig/TimedTwigEnvironment.php | 3 - composer.json | 6 +- meta/phpstan/redis.stub | 85 +++++++ phpstan.neon.dist | 4 + 15 files changed, 420 insertions(+), 242 deletions(-) create mode 100644 Cache/RedisLegacy.php create mode 100644 Cache/RedisPhp8.php create mode 100644 Cache/RedisStopwatchTrait.php create mode 100644 meta/phpstan/redis.stub diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eae3693..f152594 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,61 @@ jobs: image: redis:3.2-alpine ports: - 6379:6379 + strategy: + fail-fast: false + matrix: + php-version: + - '7.4' + - '8.0' + - '8.1' + - '8.2' + symfony-version: + - '4.4.*' + - '5.4.*' + - '6.2.*' + exclude: + - php-version: '8.2' + symfony-version: '4.4.*' + - php-version: '8.2' + symfony-version: '5.4.*' + - php-version: '8.1' + symfony-version: '4.4.*' + - php-version: '8.0' + symfony-version: '6.2.*' + - php-version: '7.4' + symfony-version: '6.2.*' + coverage: [ 'none' ] + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + tools: flex + php-version: "${{ matrix.php-version }}" + extensions: redis-5.3.7 + coverage: "${{ matrix.coverage }}" + + - name: "Allow legacy Symfony branches in CI" + run: composer config audit.block-insecure false + + - name: "Install dependencies" + uses: ramsey/composer-install@v2 + env: + SYMFONY_REQUIRE: "${{ matrix.symfony-version }}" + + - name: "Run tests" + run: composer test + + current-tests: + runs-on: ubuntu-24.04 + name: "Current tests" + services: + redis: + image: redis:7-alpine + ports: + - 6379:6379 strategy: fail-fast: false matrix: @@ -35,7 +90,7 @@ jobs: with: tools: flex php-version: "${{ matrix.php-version }}" - extensions: redis-5.3.7 + extensions: redis coverage: "${{ matrix.coverage }}" - name: "Install dependencies" @@ -53,6 +108,9 @@ jobs: fail-fast: false matrix: php-version: + - '7.4' + - '8.0' + - '8.1' - '8.2' - '8.3' - '8.4' @@ -64,6 +122,7 @@ jobs: uses: "shivammathur/setup-php@v2" with: php-version: ${{ matrix.php-version }} + tools: flex coverage: "none" - name: "Cache dependencies installed with composer" @@ -73,6 +132,9 @@ jobs: key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}" restore-keys: "php-${{ matrix.php-version }}-composer-locked-" + - name: "Allow legacy Symfony branches in CI" + run: composer config audit.block-insecure false + - name: "Install dependencies" uses: ramsey/composer-install@v2 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 94f7ec3..c98b93e 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -12,12 +12,17 @@ ->in(__DIR__ . '/tests') ; +if (PHP_VERSION_ID < 80000) { + $finder->notName('RedisPhp8.php'); +} + $rules = [ '@Symfony' => true, '@Symfony:risky' => true, // exceptions 'single_line_throw' => false, + 'modernize_strpos' => false, // php file 'concat_space' => ['spacing' => 'one'], diff --git a/Cache/Redis.php b/Cache/Redis.php index 9a2a1a6..59de691 100644 --- a/Cache/Redis.php +++ b/Cache/Redis.php @@ -2,222 +2,17 @@ namespace Intaro\PinbaBundle\Cache; -use Intaro\PinbaBundle\Stopwatch\Stopwatch; +require_once __DIR__ . '/RedisStopwatchTrait.php'; + +$redisVersion = phpversion('redis'); +if (PHP_VERSION_ID >= 80000 && is_string($redisVersion) && version_compare($redisVersion, '6.0.0', '>=')) { + require_once __DIR__ . '/RedisPhp8.php'; + class_alias(RedisPhp8::class, RedisBase::class); +} else { + require_once __DIR__ . '/RedisLegacy.php'; + class_alias(RedisLegacy::class, RedisBase::class); +} -class Redis extends \Redis +class Redis extends RedisBase { - protected $stopwatch; - protected $stopwatchAdditionalTags = []; - protected $serverName; - protected int $expireMethodArgumentsCount; - - public function addWatchedServer( - $host, - $port = 6379, - $timeout = 5 - ): void { - $this->serverName = $host . (6379 == $port ? '' : ':' . $port); - - $this->pconnect($host, $port, $timeout); - - // для совместимости с Redis 5 - $expireMethodReflection = new \ReflectionMethod(\Redis::class, 'expire'); - $this->expireMethodArgumentsCount = $expireMethodReflection->getNumberOfParameters(); - if ($this->expireMethodArgumentsCount < 2 || $this->expireMethodArgumentsCount > 3) { - throw new \RuntimeException( - 'Redis::expire method has wrong number of arguments ' . $this->expireMethodArgumentsCount . ' instead of 2 or 3' - ); - } - } - - public function setStopwatch(Stopwatch $stopwatch): void - { - $this->stopwatch = $stopwatch; - } - - public function setStopwatchTags(array $tags): void - { - $this->stopwatchAdditionalTags = $tags; - } - - protected function getStopwatchEvent($methodName) - { - $tags = $this->stopwatchAdditionalTags; - $tags['group'] = 'redis::' . $methodName; - - if ($this->serverName) { - $tags['server'] = $this->serverName; - } - - return $this->stopwatch->start($tags); - } - - public function get($key) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('get'); - } - - $result = parent::get($key); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function mGet(array $keys) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('mGet'); - } - - $result = parent::mGet($keys); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function exists($key, ...$other_keys) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('exists'); - } - - $result = parent::exists($key, ...$other_keys); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function set($key, $var, $opts = null) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('set'); - } - - $result = parent::set($key, $var, $opts); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function setex($key, $var, $expire) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('setex'); - } - - $result = parent::setex($key, $var, $expire); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function mSetNx($v) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('mSetNx'); - } - - $result = parent::mSetNx($v); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function expire($key, $expire, $mode = null) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('expire'); - } - - if (2 === $this->expireMethodArgumentsCount) { - $result = parent::expire($key, $expire); - } else { - $result = parent::expire($key, $expire, $mode); - } - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function exec() - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('exec'); - } - - $result = parent::exec(); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function delete($key, ...$other_keys) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('delete'); - } - - $result = parent::delete($key, ...$other_keys); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function sMembers($key) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('sMembers'); - } - - $result = parent::sMembers($key); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } - - public function sAdd($tag, $id, ...$other_values) - { - if ($this->stopwatch) { - $e = $this->getStopwatchEvent('sAdd'); - } - - $result = parent::sAdd($tag, $id, ...$other_values); - - if ($this->stopwatch) { - $e->stop(); - } - - return $result; - } } diff --git a/Cache/RedisLegacy.php b/Cache/RedisLegacy.php new file mode 100644 index 0000000..5ac090f --- /dev/null +++ b/Cache/RedisLegacy.php @@ -0,0 +1,89 @@ +callWithStopwatch('get', function () use ($key) { + return parent::get($key); + }); + } + + public function mGet(array $keys) + { + return $this->callWithStopwatch('mGet', function () use ($keys) { + return parent::mGet($keys); + }); + } + + public function exists($key, ...$otherKeys) + { + return $this->callWithStopwatch('exists', function () use ($key, $otherKeys) { + return parent::exists($key, ...$otherKeys); + }); + } + + public function set($key, $value, $options = null) + { + return $this->callWithStopwatch('set', function () use ($key, $value, $options) { + return parent::set($key, $value, $options); + }); + } + + public function setex($key, $expire, $value) + { + return $this->callWithStopwatch('setex', function () use ($key, $expire, $value) { + return parent::setex($key, $expire, $value); + }); + } + + public function mSetNx($keyValues) + { + return $this->callWithStopwatch('mSetNx', function () use ($keyValues) { + return parent::mSetNx($keyValues); + }); + } + + public function expire($key, $expire, $mode = null) + { + return $this->callWithStopwatch('expire', function () use ($key, $expire, $mode) { + if (2 === $this->expireMethodArgumentsCount) { + return parent::expire($key, $expire); + } + + return parent::expire($key, $expire, $mode); + }); + } + + public function exec() + { + return $this->callWithStopwatch('exec', function () { + return parent::exec(); + }); + } + + public function delete($key, ...$otherKeys) + { + return $this->callWithStopwatch('delete', function () use ($key, $otherKeys) { + return parent::delete($key, ...$otherKeys); + }); + } + + public function sMembers($key) + { + return $this->callWithStopwatch('sMembers', function () use ($key) { + return parent::sMembers($key); + }); + } + + public function sAdd($key, $value, ...$otherValues) + { + return $this->callWithStopwatch('sAdd', function () use ($key, $value, $otherValues) { + return parent::sAdd($key, $value, ...$otherValues); + }); + } +} diff --git a/Cache/RedisPhp8.php b/Cache/RedisPhp8.php new file mode 100644 index 0000000..52755b6 --- /dev/null +++ b/Cache/RedisPhp8.php @@ -0,0 +1,89 @@ +callWithStopwatch('get', function () use ($key) { + return parent::get($key); + }); + } + + public function mGet(array $keys): \Redis|array|false + { + return $this->callWithStopwatch('mGet', function () use ($keys) { + return parent::mGet($keys); + }); + } + + public function exists(mixed $key, mixed ...$otherKeys): \Redis|int|bool + { + return $this->callWithStopwatch('exists', function () use ($key, $otherKeys) { + return parent::exists($key, ...$otherKeys); + }); + } + + public function set(string $key, mixed $value, mixed $options = null): \Redis|string|bool + { + return $this->callWithStopwatch('set', function () use ($key, $value, $options) { + return parent::set($key, $value, $options); + }); + } + + public function setex(string $key, int $expire, mixed $value) + { + return $this->callWithStopwatch('setex', function () use ($key, $expire, $value) { + return parent::setex($key, $expire, $value); + }); + } + + public function mSetNx(array $keyValues): \Redis|bool + { + return $this->callWithStopwatch('mSetNx', function () use ($keyValues) { + return parent::mSetNx($keyValues); + }); + } + + public function expire(string $key, int $expire, ?string $mode = null): \Redis|bool + { + return $this->callWithStopwatch('expire', function () use ($key, $expire, $mode) { + if (2 === $this->expireMethodArgumentsCount) { + return parent::expire($key, $expire); + } + + return parent::expire($key, $expire, $mode); + }); + } + + public function exec(): \Redis|array|false + { + return $this->callWithStopwatch('exec', function () { + return parent::exec(); + }); + } + + public function delete(array|string $key, string ...$otherKeys): \Redis|int|false + { + return $this->callWithStopwatch('delete', function () use ($key, $otherKeys) { + return parent::delete($key, ...$otherKeys); + }); + } + + public function sMembers(string $key): \Redis|array|false + { + return $this->callWithStopwatch('sMembers', function () use ($key) { + return parent::sMembers($key); + }); + } + + public function sAdd(string $key, mixed $value, mixed ...$otherValues): \Redis|int|false + { + return $this->callWithStopwatch('sAdd', function () use ($key, $value, $otherValues) { + return parent::sAdd($key, $value, ...$otherValues); + }); + } +} diff --git a/Cache/RedisStopwatchTrait.php b/Cache/RedisStopwatchTrait.php new file mode 100644 index 0000000..7c75154 --- /dev/null +++ b/Cache/RedisStopwatchTrait.php @@ -0,0 +1,68 @@ +serverName = $host . (6379 == $port ? '' : ':' . $port); + + $this->pconnect($host, $port, $timeout); + + $expireMethodReflection = new \ReflectionMethod(\Redis::class, 'expire'); + $this->expireMethodArgumentsCount = $expireMethodReflection->getNumberOfParameters(); + if ($this->expireMethodArgumentsCount < 2 || $this->expireMethodArgumentsCount > 3) { + throw new \RuntimeException( + 'Redis::expire method has wrong number of arguments ' . $this->expireMethodArgumentsCount . ' instead of 2 or 3' + ); + } + } + + public function setStopwatch(Stopwatch $stopwatch): void + { + $this->stopwatch = $stopwatch; + } + + public function setStopwatchTags(array $tags): void + { + $this->stopwatchAdditionalTags = $tags; + } + + protected function getStopwatchEvent($methodName) + { + $tags = $this->stopwatchAdditionalTags; + $tags['group'] = 'redis::' . $methodName; + + if ($this->serverName) { + $tags['server'] = $this->serverName; + } + + return $this->stopwatch->start($tags); + } + + protected function callWithStopwatch($methodName, callable $callback) + { + if ($this->stopwatch) { + $event = $this->getStopwatchEvent($methodName); + } + + $result = $callback(); + + if ($this->stopwatch) { + $event->stop(); + } + + return $result; + } +} diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 763f664..189b21d 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -12,9 +12,6 @@ */ class Configuration implements ConfigurationInterface { - /** - * {@inheritDoc} - */ public function getConfigTreeBuilder(): TreeBuilder { $treeBuilder = new TreeBuilder('intaro_pinba'); diff --git a/DependencyInjection/IntaroPinbaExtension.php b/DependencyInjection/IntaroPinbaExtension.php index 5c61f11..e997958 100644 --- a/DependencyInjection/IntaroPinbaExtension.php +++ b/DependencyInjection/IntaroPinbaExtension.php @@ -14,9 +14,6 @@ */ class IntaroPinbaExtension extends Extension { - /** - * {@inheritDoc} - */ public function load(array $configs, ContainerBuilder $container): void { $configuration = new Configuration(); diff --git a/Logger/DbalLogger.php b/Logger/DbalLogger.php index 2945a17..3ca15a7 100644 --- a/Logger/DbalLogger.php +++ b/Logger/DbalLogger.php @@ -19,16 +19,13 @@ class DbalLogger implements SQLLogger * * @param Stopwatch $stopwatch A Stopwatch instance */ - public function __construct(Stopwatch $stopwatch = null, $host = null) + public function __construct(?Stopwatch $stopwatch = null, $host = null) { $this->stopwatch = $stopwatch; $this->databaseHost = $host; } - /** - * {@inheritdoc} - */ - public function startQuery($sql, array $params = null, array $types = null): void + public function startQuery($sql, ?array $params = null, ?array $types = null): void { if (null !== $this->stopwatch) { $tags = [ @@ -45,9 +42,6 @@ public function startQuery($sql, array $params = null, array $types = null): voi } } - /** - * {@inheritdoc} - */ public function stopQuery(): void { if (null !== $this->stopwatchEvent) { diff --git a/Stopwatch/Stopwatch.php b/Stopwatch/Stopwatch.php index b0b48c8..bb156e6 100644 --- a/Stopwatch/Stopwatch.php +++ b/Stopwatch/Stopwatch.php @@ -33,8 +33,7 @@ function_exists('pinba_timer_start') && function_exists('pinba_timer_add') && function_exists('pinba_get_info') && function_exists('pinba_timers_get') - && function_exists('pinba_flush') - ; + && function_exists('pinba_flush'); } public function disable(): void diff --git a/Twig/TimedTwigEngine.php b/Twig/TimedTwigEngine.php index 812d62d..75deac9 100644 --- a/Twig/TimedTwigEngine.php +++ b/Twig/TimedTwigEngine.php @@ -43,9 +43,6 @@ public function __construct(\Twig\Environment $environment, TemplateNameParserIn $this->stopwatch = $stopwatch; } - /** - * {@inheritdoc} - */ public function render($name, array $parameters = []) { $e = $this->stopwatch->start([ diff --git a/Twig/TimedTwigEnvironment.php b/Twig/TimedTwigEnvironment.php index 3b09b6b..19187a2 100644 --- a/Twig/TimedTwigEnvironment.php +++ b/Twig/TimedTwigEnvironment.php @@ -17,9 +17,6 @@ public function __construct(LoaderInterface $loader, $options = [], ?Stopwatch $ $this->stopwatch = $stopwatch; } - /** - * {@inheritdoc} - */ public function render($name, array $context = []): string { if (null !== $this->stopwatch) { diff --git a/composer.json b/composer.json index a79e5d1..55134b9 100644 --- a/composer.json +++ b/composer.json @@ -8,13 +8,13 @@ "name" : "Ilyas Salikhov" }], "require": { - "php": ">=8.2", + "php": ">=7.4", "symfony/framework-bundle" : "^4.0|^5.0|^6.0|^7.0", "symfony/yaml": "^4.0|^5.0|^6.0|^7.0" }, "require-dev": { "doctrine/dbal": "^2|^3|^4", - "nyholm/symfony-bundle-test": "^3.1", + "nyholm/symfony-bundle-test": "^2.0|^3.1", "phpunit/phpunit": "^8.5|^9.5", "symfony/phpunit-bridge": "^5.0|^6.0|^7.0", "symfony/config": "^4.4|^5.0|^6.0|^7.0", @@ -33,7 +33,7 @@ "symfony/var-exporter": "^4.4|^5.0|^6.0|^7.0", "symfony/var-dumper": "^4.4|^5.0|^6.0|^7.0", "psr/log": "~1.0|^2|^3", - "friendsofphp/php-cs-fixer": "^3.95", + "friendsofphp/php-cs-fixer": "^3.4", "twig/twig": "^v2.14 || ^3.0", "symfony/twig-bundle": "^4.4|^5.0|^6.0|^7.0", "symfony/twig-bridge": "^4.4|^5.0|^6.0|^7.0", diff --git a/meta/phpstan/redis.stub b/meta/phpstan/redis.stub new file mode 100644 index 0000000..07b5de3 --- /dev/null +++ b/meta/phpstan/redis.stub @@ -0,0 +1,85 @@ + $tags + */ + public function setStopwatchTags(array $tags): void + { + } + + public function get(string $key): mixed + { + } + + /** + * @param array $keys + * + * @return \Redis|array|false + */ + public function mGet(array $keys): \Redis|array|false + { + } + + public function exists(mixed $key, mixed ...$otherKeys): \Redis|int|bool + { + } + + public function set(string $key, mixed $value, mixed $options = null): \Redis|string|bool + { + } + + public function setex(string $key, int $expire, mixed $value): mixed + { + } + + /** + * @param array $keyValues + */ + public function mSetNx(array $keyValues): \Redis|bool + { + } + + public function expire(string $key, int $expire, ?string $mode = null): \Redis|bool + { + } + + /** + * @return \Redis|array|false + */ + public function exec(): \Redis|array|false + { + } + + /** + * @param array|string $key + */ + public function delete(array|string $key, string ...$otherKeys): \Redis|int|false + { + } + + /** + * @return \Redis|array|false + */ + public function sMembers(string $key): \Redis|array|false + { + } + + public function sAdd(string $key, mixed $value, mixed ...$otherValues): \Redis|int|false + { + } +} diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b5940fa..d68300b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -8,7 +8,11 @@ parameters: - Logger/DbalLogger.php # return type for get and mGet methods - Cache/Redis.php + - Cache/RedisLegacy.php + - Cache/RedisPhp8.php - vendor/ + scanFiles: + - meta/phpstan/redis.stub bootstrapFiles: - meta/phpstan/stub.php ignoreErrors: From 39eea50f3f2df354841c6fd71fbfa16bf0ec75c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B8=D1=80=D0=B8=D0=BB=D0=BB=20=D0=93=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BD=D0=BE=D0=B2=D0=B8=D1=87?= Date: Thu, 28 May 2026 11:27:34 +0300 Subject: [PATCH 8/8] codestyle --- .php-cs-fixer.dist.php | 1 + Cache/RedisStopwatchTrait.php | 2 +- meta/phpstan/redis.stub | 36 +++++++++++++++++++++++------------ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index c98b93e..947804a 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -23,6 +23,7 @@ // exceptions 'single_line_throw' => false, 'modernize_strpos' => false, + 'trailing_comma_in_multiline' => false, // php file 'concat_space' => ['spacing' => 'one'], diff --git a/Cache/RedisStopwatchTrait.php b/Cache/RedisStopwatchTrait.php index 7c75154..63f54b8 100644 --- a/Cache/RedisStopwatchTrait.php +++ b/Cache/RedisStopwatchTrait.php @@ -14,7 +14,7 @@ trait RedisStopwatchTrait public function addWatchedServer( $host, $port = 6379, - $timeout = 5, + $timeout = 5 ): void { $this->serverName = $host . (6379 == $port ? '' : ':' . $port); diff --git a/meta/phpstan/redis.stub b/meta/phpstan/redis.stub index 07b5de3..1cbd7c5 100644 --- a/meta/phpstan/redis.stub +++ b/meta/phpstan/redis.stub @@ -7,7 +7,7 @@ class Redis public function addWatchedServer( string $host, int $port = 6379, - float $timeout = 5, + float $timeout = 5 ): void { } @@ -22,7 +22,7 @@ class Redis { } - public function get(string $key): mixed + public function get(string $key) { } @@ -31,55 +31,67 @@ class Redis * * @return \Redis|array|false */ - public function mGet(array $keys): \Redis|array|false + public function mGet(array $keys) { } - public function exists(mixed $key, mixed ...$otherKeys): \Redis|int|bool + public function exists($key, ...$otherKeys) { } - public function set(string $key, mixed $value, mixed $options = null): \Redis|string|bool + public function set(string $key, $value, $options = null) { } - public function setex(string $key, int $expire, mixed $value): mixed + public function setex(string $key, int $expire, $value) { } /** * @param array $keyValues */ - public function mSetNx(array $keyValues): \Redis|bool + public function mSetNx(array $keyValues) { } - public function expire(string $key, int $expire, ?string $mode = null): \Redis|bool + public function expire(string $key, int $expire, ?string $mode = null) { } /** * @return \Redis|array|false */ - public function exec(): \Redis|array|false + public function exec() { } /** * @param array|string $key */ - public function delete(array|string $key, string ...$otherKeys): \Redis|int|false + public function delete($key, string ...$otherKeys) { } /** * @return \Redis|array|false */ - public function sMembers(string $key): \Redis|array|false + public function sMembers(string $key) { } - public function sAdd(string $key, mixed $value, mixed ...$otherValues): \Redis|int|false + public function sAdd(string $key, $value, ...$otherValues) + { + } + + public function multi($value = null) + { + } + + public function select(int $dbindex) + { + } + + public function flushDB($async = null) { } }