Skip to content

Commit 70da987

Browse files
authored
feature #75 Add support for Symfony 8 (2.x branch) (sstok)
This PR was merged into the 2.0 branch. Discussion ---------- | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Fixed tickets | | License | MIT Add support for Symfony 8 in the 2.x branch, this is the lowest possible branch as the 1.x branches still allow Symfony 6, which would require to much juggling with older PHP versions. This should make upgrading easier. Sorry for all the delays in development. Commits ------- 355dbfe Add support for Symfony 8
2 parents 89f0c1d + 355dbfe commit 70da987

10 files changed

Lines changed: 652 additions & 193 deletions

.github/workflows/ci.yaml

Lines changed: 11 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ name: 'CI'
33
on:
44
push:
55
branches:
6-
- main
6+
- '2.0'
77
pull_request:
88
branches:
9-
- main
9+
- '2.0'
1010

1111
jobs:
1212
cs-fixer:
@@ -22,7 +22,7 @@ jobs:
2222
steps:
2323
-
2424
name: 'Check out'
25-
uses: 'actions/checkout@v2'
25+
uses: 'actions/checkout@v6'
2626

2727
-
2828
name: 'Set up PHP'
@@ -38,7 +38,7 @@ jobs:
3838

3939
-
4040
name: 'Cache dependencies'
41-
uses: 'actions/cache@v2'
41+
uses: 'actions/cache@v4'
4242
with:
4343
path: '${{ steps.composer-cache.outputs.cache-dir }}'
4444
key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
@@ -52,49 +52,6 @@ jobs:
5252
name: 'Check the code style'
5353
run: 'make cs-full'
5454

55-
phpstan:
56-
name: 'PhpStan'
57-
58-
runs-on: 'ubuntu-latest'
59-
60-
strategy:
61-
matrix:
62-
php-version:
63-
- '8.2'
64-
65-
steps:
66-
-
67-
name: 'Check out'
68-
uses: 'actions/checkout@v2'
69-
70-
-
71-
name: 'Set up PHP'
72-
uses: 'shivammathur/setup-php@v2'
73-
with:
74-
php-version: '${{ matrix.php-version }}'
75-
coverage: 'none'
76-
77-
-
78-
name: 'Get Composer cache directory'
79-
id: 'composer-cache'
80-
run: 'echo "::set-output name=cache-dir::$(composer config cache-files-dir)"'
81-
82-
-
83-
name: 'Cache dependencies'
84-
uses: 'actions/cache@v2'
85-
with:
86-
path: '${{ steps.composer-cache.outputs.cache-dir }}'
87-
key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"
88-
restore-keys: 'php-${{ matrix.php-version }}-composer-locked-'
89-
90-
-
91-
name: 'Install dependencies'
92-
run: 'composer update --no-progress --prefer-stable'
93-
94-
-
95-
name: 'Run PhpStan'
96-
run: 'vendor/bin/phpstan analyze --no-progress'
97-
9855
tests:
9956
name: 'PHPUnit'
10057

@@ -106,21 +63,22 @@ jobs:
10663
-
10764
php-version: '8.2'
10865
composer-options: '--prefer-stable'
109-
symfony-version: '6.3'
66+
symfony-version: '^6.4'
67+
11068
-
11169
php-version: '8.2'
11270
composer-options: '--prefer-stable'
113-
symfony-version: '^6.4'
71+
symfony-version: '^7.4'
11472

11573
-
116-
php-version: '8.2'
74+
php-version: '8.4'
11775
composer-options: '--prefer-stable'
118-
symfony-version: '^7.0'
76+
symfony-version: '^8.0'
11977

12078
steps:
12179
-
12280
name: 'Check out'
123-
uses: 'actions/checkout@v2'
81+
uses: 'actions/checkout@v6'
12482

12583
-
12684
name: 'Set up PHP'
@@ -136,7 +94,7 @@ jobs:
13694

13795
-
13896
name: 'Cache dependencies'
139-
uses: 'actions/cache@v2'
97+
uses: 'actions/cache@v4'
14098
with:
14199
path: '${{ steps.composer-cache.outputs.cache-dir }}'
142100
key: "php-${{ matrix.php-version }}-composer-locked-${{ hashFiles('composer.lock') }}"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
symfony.lock
77
.phpunit.result.cache
88
.php-cs-fixer.cache
9+
.phpunit.cache/

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,18 @@
1919
}
2020
],
2121
"require": {
22-
"php": ">=8.2",
23-
"symfony/config": "^6.0 || ^7.0",
22+
"php": "^8.2",
23+
"symfony/config": "^6.4 || ^7.4 || ^8.0",
2424
"symfony/polyfill-mbstring": "^1.5.0",
25-
"symfony/translation": "^6.0 || ^7.0",
26-
"symfony/validator": "^6.0 || ^7.0"
25+
"symfony/translation": "^6.4 || ^7.4 || ^8.0",
26+
"symfony/validator": "^6.4 || ^7.4 || ^8.0"
2727
},
2828
"require-dev": {
2929
"phpstan/phpstan": "^1.10",
3030
"phpstan/phpstan-phpunit": "^1.1",
3131
"phpstan/phpstan-symfony": "^1.2",
3232
"phpunit/phpunit": "^9.5",
33-
"symfony/phpunit-bridge": "^6.0 || ^7.0"
33+
"symfony/phpunit-bridge": "^7.4 || ^8.0"
3434
},
3535
"minimum-stability": "dev",
3636
"prefer-stable": true,

phpunit.xml.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<ini name="memory_limit" value="-1"/>
1818
<ini name="default_charset" value="UTF-8"/>
1919

20-
<env name="SYMFONY_DEPRECATIONS_HELPER" value="max[self]=0" />
20+
<env name="SYMFONY_DEPRECATIONS_HELPER" value="disabled=1" />
2121
</php>
2222

2323
<testsuites>
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the RollerworksPasswordStrengthValidator package.
7+
*
8+
* (c) Sebastiaan Stok <s.stok@rollerscapes.net>
9+
*
10+
* This source file is subject to the MIT license that is bundled
11+
* with this source code in the file LICENSE.
12+
*/
13+
14+
namespace Rollerworks\Component\PasswordStrength\Validator\Constraints;
15+
16+
use Symfony\Component\Validator\Constraint;
17+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
18+
use Symfony\Component\Validator\Exception\InvalidOptionsException;
19+
use Symfony\Component\Validator\Exception\MissingOptionsException;
20+
21+
if (method_exists(Constraint::class, 'normalizeOptions')) {
22+
/**
23+
* @internal
24+
*/
25+
trait ConstraintCompatTrait
26+
{
27+
protected function initOptions(?array $options, ?array $groups, mixed $payload): void
28+
{
29+
// Noop
30+
}
31+
}
32+
} else {
33+
34+
/**
35+
* @internal
36+
*/
37+
trait ConstraintCompatTrait
38+
{
39+
protected function initOptions(?array $options, ?array $groups, mixed $payload): void
40+
{
41+
if ($options === null) {
42+
return;
43+
}
44+
45+
trigger_deprecation('symfony/validator', '7.4', 'Support for evaluating options in the %1$s class is deprecated. Initialize properties in the constructor of %1$s instead.', static::class);
46+
47+
$options = $this->normalizeOptions($options);
48+
49+
if ($groups !== null) {
50+
$options['groups'] = $groups;
51+
}
52+
$options['payload'] = $payload ?? $options['payload'] ?? null;
53+
54+
foreach ($options as $name => $value) {
55+
$this->{$name} = $value;
56+
}
57+
}
58+
59+
/**
60+
* @deprecated since Symfony 7.4
61+
*
62+
* @return array<string, mixed>
63+
*/
64+
protected function normalizeOptions(mixed $options): array
65+
{
66+
$normalizedOptions = [];
67+
$defaultOption = $this->getDefaultOption(false);
68+
$invalidOptions = [];
69+
$missingOptions = array_flip($this->getRequiredOptions(false));
70+
$knownOptions = get_class_vars(static::class);
71+
72+
if (\is_array($options) && isset($options['value']) && ! property_exists($this, 'value')) {
73+
if ($defaultOption === null) {
74+
throw new ConstraintDefinitionException(\sprintf('No default option is configured for constraint "%s".', static::class));
75+
}
76+
77+
$options[$defaultOption] = $options['value'];
78+
unset($options['value']);
79+
}
80+
81+
if (\is_array($options)) {
82+
reset($options);
83+
}
84+
85+
if ($options && \is_array($options) && \is_string(key($options))) {
86+
foreach ($options as $option => $value) {
87+
if (\array_key_exists($option, $knownOptions)) {
88+
$normalizedOptions[$option] = $value;
89+
unset($missingOptions[$option]);
90+
} else {
91+
$invalidOptions[] = $option;
92+
}
93+
}
94+
} elseif ($options !== null && ! (\is_array($options) && \count($options) === 0)) {
95+
if ($defaultOption === null) {
96+
throw new ConstraintDefinitionException(\sprintf('No default option is configured for constraint "%s".', static::class));
97+
}
98+
99+
if (\array_key_exists($defaultOption, $knownOptions)) {
100+
$normalizedOptions[$defaultOption] = $options;
101+
unset($missingOptions[$defaultOption]);
102+
} else {
103+
$invalidOptions[] = $defaultOption;
104+
}
105+
}
106+
107+
if (\count($invalidOptions) > 0) {
108+
throw new InvalidOptionsException(\sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), static::class), $invalidOptions);
109+
}
110+
111+
if (\count($missingOptions) > 0) {
112+
throw new MissingOptionsException(\sprintf('The options "%s" must be set for constraint "%s".', implode('", "', array_keys($missingOptions)), static::class), array_keys($missingOptions));
113+
}
114+
115+
return $normalizedOptions;
116+
}
117+
118+
/**
119+
* Returns the name of the default option.
120+
*
121+
* Override this method to define a default option.
122+
*
123+
* @deprecated since Symfony 7.4
124+
* @see __construct()
125+
*/
126+
public function getDefaultOption(): ?string
127+
{
128+
if (\func_num_args() === 0 || func_get_arg(0)) {
129+
trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__);
130+
}
131+
132+
return null;
133+
}
134+
135+
/**
136+
* Returns the name of the required options.
137+
*
138+
* Override this method if you want to define required options.
139+
*
140+
* @return string[]
141+
*
142+
* @deprecated since Symfony 7.4
143+
* @see __construct()
144+
*/
145+
public function getRequiredOptions(): array
146+
{
147+
if (\func_num_args() === 0 || func_get_arg(0)) {
148+
trigger_deprecation('symfony/validator', '7.4', 'The %s() method is deprecated.', __METHOD__);
149+
}
150+
151+
return [];
152+
}
153+
}
154+
}

src/Validator/Constraints/PasswordRequirements.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515

1616
/**
1717
* @Annotation
18-
*
1918
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
2019
*/
2120
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
2221
class PasswordRequirements extends Constraint
2322
{
23+
use ConstraintCompatTrait;
24+
2425
public string $tooShortMessage = 'Your password must be at least {{length}} characters long.';
2526
public string $missingLettersMessage = 'Your password must include at least one letter.';
2627
public string $requireCaseDiffMessage = 'Your password must include both upper and lower case letters.';
@@ -49,6 +50,7 @@ public function __construct(
4950
?string $missingSpecialCharacterMessage = null
5051
) {
5152
parent::__construct($options ?? [], $groups, $payload);
53+
$this->initOptions($options, $groups, $payload);
5254

5355
$this->tooShortMessage = $tooShortMessage ?? $this->tooShortMessage;
5456
$this->missingLettersMessage = $missingLettersMessage ?? $this->missingLettersMessage;

src/Validator/Constraints/PasswordStrength.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515

1616
/**
1717
* @Annotation
18-
*
1918
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
2019
*/
2120
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
2221
class PasswordStrength extends Constraint
2322
{
23+
use ConstraintCompatTrait;
24+
2425
public string $tooShortMessage = 'Your password must be at least {{length}} characters long.';
2526
public string $message = 'password_too_weak';
2627
public int $minLength = 6;
@@ -51,6 +52,7 @@ public function __construct(
5152
}
5253

5354
parent::__construct($finalOptions, $groups, $payload);
55+
$this->initOptions($finalOptions, $groups, $payload);
5456

5557
$this->minLength = $minLength ?? $this->minLength;
5658
$this->unicodeEquality = $unicodeEquality ?? $this->unicodeEquality;

0 commit comments

Comments
 (0)