44
55namespace PHPModelGenerator \Model \Property ;
66
7+ use PHPModelGenerator \Attributes \JsonPointer ;
8+ use PHPModelGenerator \Attributes \SchemaName ;
79use PHPModelGenerator \Exception \SchemaException ;
810use PHPModelGenerator \Model \Attributes \PhpAttribute ;
911use PHPModelGenerator \Model \GeneratorConfiguration ;
2123 */
2224class PropertyProxy extends AbstractProperty
2325{
26+ private ?JsonSchema $ overrideJsonSchema = null ;
27+ private ?PhpAttribute $ overrideJsonPointer = null ;
28+
2429 /**
2530 * PropertyProxy constructor.
2631 *
@@ -296,7 +301,20 @@ public function getNestedSchema(): ?Schema
296301 */
297302 public function getJsonSchema (): JsonSchema
298303 {
299- return $ this ->getProperty ()->getJsonSchema ();
304+ return $ this ->overrideJsonSchema ?? $ this ->getProperty ()->getJsonSchema ();
305+ }
306+
307+ /**
308+ * @inheritdoc
309+ *
310+ * Stores a local override rather than delegating to the underlying property, preventing
311+ * mutation of a shared $ref-resolved property when only this proxy's schema must change.
312+ */
313+ public function setJsonSchema (JsonSchema $ jsonSchema ): static
314+ {
315+ $ this ->overrideJsonSchema = $ jsonSchema ;
316+
317+ return $ this ;
300318 }
301319
302320 /**
@@ -317,6 +335,16 @@ public function isInternal(): bool
317335 return $ this ->getProperty ()->isInternal ();
318336 }
319337
338+ /**
339+ * @inheritdoc
340+ */
341+ public function filterAttributes (callable $ filter ): static
342+ {
343+ $ this ->getProperty ()->filterAttributes ($ filter );
344+
345+ return $ this ;
346+ }
347+
320348 /**
321349 * @inheritdoc
322350 */
@@ -330,11 +358,45 @@ public function addAttribute(
330358 return $ this ;
331359 }
332360
361+ /**
362+ * Store the pointer attribute locally so this proxy can show a different JsonPointer from
363+ * the shared underlying property (each reference site has its own pointer).
364+ */
365+ public function overrideJsonPointer (PhpAttribute $ attribute ): static
366+ {
367+ $ this ->overrideJsonPointer = $ attribute ;
368+
369+ return $ this ;
370+ }
371+
333372 /**
334373 * @inheritdoc
374+ *
375+ * Replaces the SchemaName attribute from the underlying shared property with one that
376+ * carries the proxy's own name. Two proxies sharing the same $ref definition would
377+ * otherwise both report the first property's name via the shared underlying attribute.
378+ *
379+ * When a JsonPointer override is set, all existing JsonPointer attributes (there may be
380+ * multiple when the underlying property was synthesised from composition branches) are
381+ * removed and replaced with a single attribute pointing to the reference site.
335382 */
336383 public function getAttributes (): array
337384 {
338- return $ this ->getProperty ()->getAttributes ();
385+ $ attributes = array_map (
386+ fn (PhpAttribute $ attribute ): PhpAttribute => $ attribute ->getFqcn () === SchemaName::class
387+ ? new PhpAttribute (SchemaName::class, [$ this ->name ])
388+ : $ attribute ,
389+ $ this ->getProperty ()->getAttributes (),
390+ );
391+
392+ if ($ this ->overrideJsonPointer !== null ) {
393+ $ attributes = array_values (array_filter (
394+ $ attributes ,
395+ static fn (PhpAttribute $ attribute ): bool => $ attribute ->getFqcn () !== JsonPointer::class,
396+ ));
397+ $ attributes [] = $ this ->overrideJsonPointer ;
398+ }
399+
400+ return $ attributes ;
339401 }
340402}
0 commit comments