@@ -881,6 +881,28 @@ public function testSafeUpdateRecursiveIncludesSavingHandlers(): void
881
881
"A saving handler on Custom Saving Handler returned false but provided no reason. "
882
882
], array_map (fn ($ e ) => ($ e instanceof JsonSchemaValidationException) ? $ e ->errorsAsMultilineString () : $ e ->getMessage (), $ caughtExceptions ));
883
883
}
884
+
885
+ public function testSafeUpdateRecursiveIncludesAttributeMutators (): void
886
+ {
887
+ $ model = $ this ->makeMockModel ();
888
+ $ jsonModel = new CustomAttributeSetter ($ model , 'data ' );
889
+ $ caughtExceptions = [];
890
+ $ jsonModel ->safeUpdateRecursive (['shirt ' => 'red ' , 'bestCaptain ' => 'Solo ' ], caughtExceptions: $ caughtExceptions );
891
+ self ::assertCanonicallySame (['shirt ' => 'red ' ], $ jsonModel );
892
+ self ::assertCanonicallySame (["Sorry, Solo is not a valid choice for Best Star Trek Captain. " ], array_map (fn ($ e ) => $ e ->getMessage (), $ caughtExceptions ));
893
+
894
+ // can mix schema and attribute mutator problems
895
+ $ caughtExceptions = [];
896
+ $ jsonModel ->safeUpdateRecursive (['shirt ' => 'orange ' , 'bestCaptain ' => 'Starbuck ' , 'tribbles ' => 14 ], caughtExceptions: $ caughtExceptions );
897
+ self ::assertCanonicallySame ([
898
+ 'shirt ' => 'red ' , // orange is invalid in the schema, reverted
899
+ 'tribbles ' => 14
900
+ ], $ jsonModel );
901
+ self ::assertCanonicallySame ([
902
+ "The properties must match schema: shirt \nThe data should match one item from enum " ,
903
+ "Sorry, Starbuck is not a valid choice for Best Star Trek Captain. "
904
+ ], array_map (fn ($ e ) => ($ e instanceof JsonSchemaValidationException) ? $ e ->errorsAsMultilineString () : $ e ->getMessage (), $ caughtExceptions ));
905
+ }
884
906
}
885
907
886
908
/**
@@ -911,6 +933,20 @@ protected static function boot()
911
933
}
912
934
}
913
935
936
+ class CustomAttributeSetter extends JsonModel
937
+ {
938
+ public const SCHEMA = '{"properties":{"shirt":{"enum":["red", "gold"]}}} ' ;
939
+ public function setBestCaptainAttribute ($ value ): void
940
+ {
941
+ if ($ value === 'Saru ' ) {
942
+ $ this ->attributes ['bestCaptain ' ] = $ value ;
943
+ } else {
944
+ throw new DomainException ("Sorry, {$ value } is not a valid choice for Best Star Trek Captain. " );
945
+ }
946
+ }
947
+ }
948
+
949
+
914
950
class DownstreamModel extends JsonModel
915
951
{
916
952
use HasJsonModelAttributes;
0 commit comments