88use Attributes \Validation \Exceptions \ContinueValidationException ;
99use Attributes \Validation \Exceptions \StopValidationException ;
1010use Attributes \Validation \Exceptions \ValidationException ;
11+ use Attributes \Validation \Options as Options ;
1112use Attributes \Validation \Validators \AttributesValidator ;
1213use Attributes \Validation \Validators \ChainValidator ;
1314use Attributes \Validation \Validators \PropertyValidator ;
1415use Attributes \Validation \Validators \TypeHintValidator ;
1516use ReflectionClass ;
1617use ReflectionException ;
18+ use ReflectionProperty ;
1719use Respect \Validation \Exceptions \ValidationException as RespectValidationException ;
1820use Respect \Validation \Factory ;
1921
@@ -31,6 +33,7 @@ public function __construct(?PropertyValidator $validator = null, bool $stopFirs
3133 $ this ->context = $ context ?? new Context ;
3234 $ this ->context ->set ('option.stopFirstError ' , $ stopFirstError );
3335 $ this ->context ->set ('option.strict ' , $ strict );
36+ $ this ->context ->set ('option.alias.generator ' , fn (string $ name ) => $ name );
3437 $ this ->validator = $ this ->context ->getOptional (PropertyValidator::class, $ validator ) ?? $ this ->getDefaultPropertyValidator ();
3538 $ this ->context ->set (PropertyValidator::class, $ this ->validator );
3639
@@ -69,32 +72,30 @@ public function validate(array $data, string|object $model): object
6972 $ reflectionClass = new ReflectionClass ($ validModel );
7073 $ errorInfo = $ this ->context ->getOptional (ErrorInfo::class) ?: new ErrorInfo ($ this ->context );
7174 $ this ->context ->set (ErrorInfo::class, $ errorInfo , override: true );
75+ $ defaultAliasGenerator = $ this ->getDefaultAliasGenerator ($ reflectionClass );
7276 foreach ($ reflectionClass ->getProperties () as $ reflectionProperty ) {
7377 $ propertyName = $ reflectionProperty ->getName ();
78+ $ aliasName = $ this ->getAliasName ($ reflectionProperty , $ defaultAliasGenerator );
7479 $ this ->context ->push ('internal.currentProperty ' , $ propertyName );
7580
76- if (! array_key_exists ($ propertyName , $ data )) {
81+ if (! array_key_exists ($ aliasName , $ data )) {
7782 if (! $ reflectionProperty ->isInitialized ($ validModel )) {
78- $ errorInfo ->addError ("Missing required property ' $ propertyName ' " );
83+ $ errorInfo ->addError ("Missing required property ' $ aliasName ' " );
7984 }
8085
8186 $ this ->context ->pop ('internal.currentProperty ' );
8287
8388 continue ;
8489 }
8590
86- $ propertyValue = $ data [$ propertyName ];
91+ $ propertyValue = $ data [$ aliasName ];
8792 $ property = new Property ($ reflectionProperty , $ propertyValue , $ validModel ::class);
8893 $ this ->context ->set (Property::class, $ property , override: true );
8994
9095 try {
9196 $ this ->validator ->validate ($ property , $ this ->context );
9297 $ reflectionProperty ->setValue ($ validModel , $ property ->getValue ());
9398 } catch (ValidationException |RespectValidationException $ error ) {
94- if ($ error ->getMessage () == 'Invalid data ' && $ this ->context ->get ('option.stopFirstError ' )) {
95- break ;
96- }
97-
9899 $ errorInfo ->addError ($ error );
99100 } catch (ContinueValidationException $ error ) {
100101 } catch (StopValidationException $ error ) {
@@ -119,4 +120,44 @@ private function getDefaultPropertyValidator(): PropertyValidator
119120
120121 return $ chainRulesExtractor ;
121122 }
123+
124+ /**
125+ * Retrieves the default alias generator for a given class
126+ *
127+ * @throws ContextPropertyException
128+ */
129+ private function getDefaultAliasGenerator (ReflectionClass $ reflectionClass ): callable
130+ {
131+ $ allAttributes = $ reflectionClass ->getAttributes (Options \AliasGenerator::class);
132+ foreach ($ allAttributes as $ attribute ) {
133+ $ instance = $ attribute ->newInstance ();
134+
135+ return $ instance ->getAliasGenerator ();
136+ }
137+
138+ $ aliasGenerator = $ this ->context ->get ('option.alias.generator ' );
139+ if (is_callable ($ aliasGenerator )) {
140+ return $ aliasGenerator ;
141+ }
142+
143+ $ aliasGenerator = new Options \AliasGenerator ($ aliasGenerator );
144+
145+ return $ aliasGenerator ->getAliasGenerator ();
146+ }
147+
148+ /**
149+ * Retrieves the alias for a given property
150+ */
151+ private function getAliasName (ReflectionProperty $ reflectionProperty , callable $ defaultAliasGenerator ): string
152+ {
153+ $ propertyName = $ reflectionProperty ->getName ();
154+ $ allAttributes = $ reflectionProperty ->getAttributes (Options \Alias::class);
155+ foreach ($ allAttributes as $ attribute ) {
156+ $ instance = $ attribute ->newInstance ();
157+
158+ return $ instance ->getAlias ($ propertyName );
159+ }
160+
161+ return $ defaultAliasGenerator ($ propertyName );
162+ }
122163}
0 commit comments