66use Orisai \Exceptions \Logic \InvalidState ;
77use Orisai \Exceptions \Message ;
88use Orisai \ObjectMapper \Meta \Compile \CompileMeta ;
9+ use Orisai \ObjectMapper \Meta \Compile \FieldCompileMeta ;
910use Orisai \ObjectMapper \Meta \MetaDefinition ;
1011use Orisai \ReflectionMeta \Structure \PropertyStructure ;
1112use function array_key_first ;
@@ -60,24 +61,25 @@ public function resolveProperties(CompileMeta $meta): array
6061 $ scopedDefinitions = [];
6162
6263 foreach ($ property ->getDefinitions () as $ definition ) {
63- $ this ->checkScopeHandlerCompatibility ($ definition );
6464 $ scope = $ definition ->getScope ();
65+ $ handler = $ definition ->getHandler ();
66+
67+ if (!is_a ($ handler , $ scope , true )) {
68+ $ this ->throwHandlerIncompatibleWithScope ($ definition );
69+ }
70+
6571 $ config = $ this ->getConfig ($ definition );
6672
6773 //TODO - testovat, že target anotace/atributu odpovídá našemu Target
6874 $ targets = $ config ->targets ;
6975 if (!in_array ($ target , $ targets , true )) {
70- //TODO - použitý target není pro tuhle definici povolený její skupinou
71- // - vypsat kde je definice použitá
72- throw new Exception ('a - ' . $ propertyStructure ->getSource ()->toString ());
76+ $ this ->throwTargetIsNotAllowed ($ target , $ definition , $ propertyStructure );
7377 }
7478
7579 $ hierarchy = $ config ->hierarchyPosition ;
7680 //TODO - dovolit první třídu, nejen trait? co když bude property definovaná skrze interface?
77- if ($ hierarchy === HierarchyPosition::firstType () && $ property !== $ firstGroupedProperty ) {
78- throw new Exception (
79- 'e - ' . $ propertyStructure ->getSource ()->toString () . ' ' . get_class ($ definition ),
80- );
81+ if ($ property !== $ firstGroupedProperty && $ hierarchy === HierarchyPosition::firstType ()) {
82+ $ this ->throwDefinitionNotUsedAboveFirstOccurrence ($ definition , $ propertyStructure , $ target , $ firstGroupedProperty );
8183 }
8284
8385 $ scopesByProperty [$ propertyName ][$ scope ] = true ;
@@ -113,30 +115,33 @@ public function resolveProperties(CompileMeta $meta): array
113115 return $ scopedProperties ;
114116 }
115117
116- private function checkScopeHandlerCompatibility (MetaDefinition $ definition ): void
118+ /**
119+ * @return never
120+ */
121+ private function throwHandlerIncompatibleWithScope (MetaDefinition $ definition ): void
117122 {
123+ $ className = get_class ($ definition );
118124 $ scope = $ definition ->getScope ();
119125 $ handler = $ definition ->getHandler ();
120126
121- if (!is_a ($ handler , $ scope , true )) {
122- $ message = Message::create ()
123- ->withContext ('Resolving definition . ' . get_class ($ definition ) . '. ' )
124- ->withProblem ("Handler $ handler is incompatible with scope $ scope. " )
125- ->withSolution ('Handler must be either same or a subclass of scope. ' );
127+ $ message = Message::create ()
128+ ->withContext ("Resolving definition ' $ className'. " )
129+ ->withProblem ("Handler ' $ handler' is incompatible with scope ' $ scope'. " )
130+ ->withSolution ('Handler must be either same or a subclass of scope. ' );
126131
127- throw InvalidState::create ()
128- ->withMessage ($ message );
129- }
132+ throw InvalidState::create ()
133+ ->withMessage ($ message );
130134 }
131135
132136 private function getConfig (MetaDefinition $ definition ): ScopeConfig
133137 {
134138 $ scope = $ definition ->getScope ();
135139 $ config = $ this ->scopeConfigs [$ scope ] ?? null ;
136140 if ($ config === null ) {
141+ $ className = get_class ($ definition );
137142 $ message = Message::create ()
138- ->withContext (' Resolving definition . ' . get_class ( $ definition ) . ' . ' )
139- ->withProblem (' No config exists for scope ' . $ scope . ' returned by the definition. ' )
143+ ->withContext (" Resolving definition ' $ className '. " )
144+ ->withProblem (" No config exists for scope ' $ scope' returned by the definition. " )
140145 ->withSolution ('Add configuration to scope resolver or use an existing scope in the definition. ' );
141146
142147 throw InvalidState::create ()
@@ -146,4 +151,45 @@ private function getConfig(MetaDefinition $definition): ScopeConfig
146151 return $ config ;
147152 }
148153
154+ /**
155+ * @return never
156+ */
157+ private function throwTargetIsNotAllowed (
158+ Target $ target ,
159+ MetaDefinition $ definition ,
160+ PropertyStructure $ propertyStructure
161+ ): void
162+ {
163+ $ className = get_class ($ definition );
164+ $ message = Message::create ()
165+ ->withContext ("Resolving metadata of ' {$ propertyStructure ->getSource ()->toString ()}'. " )
166+ ->withProblem ("Used definition ' $ className' does not allow to be used on ' $ target ->value '. " );
167+
168+ throw InvalidState::create ()
169+ ->withMessage ($ message );
170+ }
171+
172+ /**
173+ * @return never
174+ */
175+ private function throwDefinitionNotUsedAboveFirstOccurrence (
176+ MetaDefinition $ definition ,
177+ PropertyStructure $ propertyStructure ,
178+ Target $ target ,
179+ FieldCompileMeta $ firstGroupedProperty
180+ ): void
181+ {
182+ $ className = get_class ($ definition );
183+
184+ $ message = Message::create ()
185+ ->withContext ("Resolving metadata of ' {$ propertyStructure ->getSource ()->toString ()}'. " )
186+ ->withProblem (
187+ "Used definition ' $ className' can be used only on the first ' $ target ->value ' occurrence, "
188+ . " ' {$ firstGroupedProperty ->getPropertyStructure ()->getSource ()->toString ()}'. "
189+ );
190+
191+ throw InvalidState::create ()
192+ ->withMessage ($ message );
193+ }
194+
149195}
0 commit comments