Skip to content

Commit 71abd74

Browse files
authored
Merge pull request #154 from wmde/trait-alternative
Create alternative to CanValidateField trait
2 parents 2aa0b24 + c1d4373 commit 71abd74

File tree

5 files changed

+151
-2
lines changed

5 files changed

+151
-2
lines changed

src/CanValidateField.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
namespace WMDE\FunValidators;
66

77
/**
8-
* @deprecated this trait is used in other repositories and cannot be tested here properly,
9-
* thus it should be turned into a helper class instead or get the behaviour extracted in another way
8+
* @deprecated Use {@see WMDE\FunValidators\ValidationResult::setSource()} instead
109
*/
1110
trait CanValidateField {
1211

src/ConstraintViolation.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ public function getSource(): string {
3333
}
3434

3535
public function setSource( string $source ): void {
36+
if ( $this->source && $this->source !== $source ) {
37+
trigger_error( 'Source is already set, overwriting it will be a logic exception in the future', E_USER_DEPRECATED );
38+
}
3639
$this->source = $source;
3740
}
3841

src/ValidationResult.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,32 @@ public function getViolations(): array {
3030
return $this->violations;
3131
}
3232

33+
/**
34+
* @deprecated Use {@see setSourceForAllViolations()} instead
35+
*/
36+
public function setSource( string $sourceName ): self {
37+
return $this->setSourceForAllViolations( $sourceName );
38+
}
39+
40+
/**
41+
* Set source of an error in all violations.
42+
*
43+
* This method is meant for validation results that come from one source,
44+
* e.g. a validator like {@see WMDE\FunValidators\Validators\RequiredFieldValidator}
45+
* or {@see WMDE\FunValidators\Validators\StringLengthValidator}
46+
*
47+
* DO NOT call it on validation results that come from validators
48+
* that validate several sources. In those cases, the responsibility to
49+
* set the source is with the validator and not its calling code.
50+
*/
51+
public function setSourceForAllViolations( string $sourceName ): self {
52+
foreach ( $this->violations as $violation ) {
53+
$violation->setSource( $sourceName );
54+
}
55+
return $this;
56+
}
57+
58+
public function getFirstViolation(): ?ConstraintViolation {
59+
return $this->violations[0] ?? null;
60+
}
3361
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare( strict_types = 1 );
4+
5+
namespace WMDE\FunValidators\Tests\Unit;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\TestCase;
9+
use WMDE\FunValidators\ConstraintViolation;
10+
11+
#[CoversClass( ConstraintViolation::class )]
12+
class ConstraintViolationTest extends TestCase {
13+
public function testConstructorSetsProperties(): void {
14+
$constraintViolation = new ConstraintViolation( "1nval1d", "no_mix_of_numbers_and_letters", "username" );
15+
16+
$this->assertSame( 'no_mix_of_numbers_and_letters', $constraintViolation->getMessageIdentifier() );
17+
$this->assertSame( '1nval1d', $constraintViolation->getValue() );
18+
$this->assertSame( 'username', $constraintViolation->getSource() );
19+
}
20+
21+
public function testSetSource(): void {
22+
$constraintViolation = new ConstraintViolation( "1nval1d", "no_mix_of_numbers_and_letters" );
23+
24+
$constraintViolation->setSource( 'access_code' );
25+
26+
$this->assertSame( 'access_code', $constraintViolation->getSource() );
27+
}
28+
29+
/**
30+
* We'll change this to an exception check when our other libraries don't trigger deprecations any more
31+
*/
32+
public function testSetSourceDeprecatesOverridingExistingSource(): void {
33+
$constraintViolation = new ConstraintViolation( "1nval1d", "no_mix_of_numbers_and_letters", 'username' );
34+
$hasTriggeredDeprecation = false;
35+
// @phpstan-ignore-next-line argument.type
36+
set_error_handler( static function ()use( &$hasTriggeredDeprecation ){
37+
$hasTriggeredDeprecation = true;
38+
}, E_USER_DEPRECATED );
39+
40+
$constraintViolation->setSource( 'access_code' );
41+
42+
restore_error_handler();
43+
$this->assertTrue( $hasTriggeredDeprecation );
44+
}
45+
46+
/**
47+
* We'll change this to an exception check when our other libraries don't trigger deprecations any more
48+
*/
49+
public function testSetSourceAllowsOverridingWhenSourceNameMatches(): void {
50+
$constraintViolation = new ConstraintViolation( "1nval1d", "no_mix_of_numbers_and_letters", 'username' );
51+
$hasTriggeredDeprecation = false;
52+
// @phpstan-ignore-next-line argument.type
53+
set_error_handler( static function ()use( &$hasTriggeredDeprecation ){
54+
$hasTriggeredDeprecation = true;
55+
}, E_USER_DEPRECATED );
56+
57+
$constraintViolation->setSource( 'username' );
58+
59+
restore_error_handler();
60+
$this->assertFalse( $hasTriggeredDeprecation );
61+
}
62+
63+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
declare( strict_types = 1 );
4+
5+
namespace WMDE\FunValidators\Tests\Unit;
6+
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\TestCase;
9+
use WMDE\FunValidators\ConstraintViolation;
10+
use WMDE\FunValidators\ValidationResult;
11+
12+
#[CoversClass( ValidationResult::class )]
13+
class ValidationResultTest extends TestCase {
14+
public function testResultWithoutViolationsIsSuccessful(): void {
15+
$result = new ValidationResult();
16+
17+
$this->assertTrue( $result->isSuccessful() );
18+
$this->assertFalse( $result->hasViolations() );
19+
}
20+
21+
public function testResultWithViolationsIsNotSuccessful(): void {
22+
$violation1 = new ConstraintViolation( 'value?', 'test_message_1' );
23+
$violation2 = new ConstraintViolation( 'value!', 'test_message_2' );
24+
$result = new ValidationResult( $violation1, $violation2 );
25+
26+
$this->assertFalse( $result->isSuccessful() );
27+
$this->assertTrue( $result->hasViolations() );
28+
$this->assertSame( [ $violation1, $violation2 ], $result->getViolations() );
29+
}
30+
31+
public function testSetSourceForAllViolationsChangesAllViolations(): void {
32+
$violation1 = new ConstraintViolation( 'value?', 'test_message_1' );
33+
$violation2 = new ConstraintViolation( 'value!', 'test_message_2' );
34+
$result = new ValidationResult( $violation1, $violation2 );
35+
36+
$result->setSourceForAllViolations( 'a_test_field' );
37+
38+
$this->assertSame( 'a_test_field', $violation1->getSource() );
39+
$this->assertSame( 'a_test_field', $violation2->getSource() );
40+
}
41+
42+
public function testGetFirstViolationReturnsFirstViolation(): void {
43+
$violation1 = new ConstraintViolation( 'value?', 'test_message_1' );
44+
$violation2 = new ConstraintViolation( 'value!', 'test_message_2' );
45+
$result = new ValidationResult( $violation1, $violation2 );
46+
47+
$this->assertSame( $violation1, $result->getFirstViolation() );
48+
}
49+
50+
public function testGetFirstViolationReturnsNullWhenThereAreNoViolations(): void {
51+
$result = new ValidationResult();
52+
53+
$this->assertNull( $result->getFirstViolation() );
54+
}
55+
56+
}

0 commit comments

Comments
 (0)