1414use EventEngine \Data \ImmutableRecord ;
1515use EventEngine \Data \ImmutableRecordLogic ;
1616use EventEngine \JsonSchema \Exception \InvalidArgumentException ;
17+ use EventEngine \JsonSchema \RecordLogic \TypeDetector ;
1718use EventEngine \Schema \TypeSchema ;
1819
1920trait JsonSchemaAwareRecordLogic
@@ -30,6 +31,28 @@ public static function __schema(): TypeSchema
3031 return self ::generateSchemaFromPropTypeMap ();
3132 }
3233
34+ /**
35+ * Override method to return a list property keys that are optional
36+ *
37+ * @return array
38+ */
39+ private static function __optionalProperties (): array
40+ {
41+ return [];
42+ }
43+
44+ /**
45+ * If a property type is a class and that class implements JsonSchemaAwareRecord the resulting JsonSchema
46+ * for that type can either be a TypeRef (no nested schema allowed - default logic) or an object schema derived
47+ * from JsonSchemaAwareRecord::__schema (enabled by returning true from the method)
48+ *
49+ * @return bool
50+ */
51+ private static function __allowNestedSchema (): bool
52+ {
53+ return false ;
54+ }
55+
3356 /**
3457 * @param array $arrayPropTypeMap Map of array property name to array item type
3558 * @return Type
@@ -70,20 +93,26 @@ private static function generateSchemaFromPropTypeMap(array $arrayPropTypeMap =
7093 } elseif ($ arrayItemType === ImmutableRecord::PHP_TYPE_ARRAY ) {
7194 throw new InvalidArgumentException ("Array item type of property $ prop must not be 'array', only a scalar type or an existing class can be used as array item type. " );
7295 } else {
73- $ arrayItemSchema = JsonSchema:: typeRef ( self ::getTypeFromClass ($ arrayItemType) );
96+ $ arrayItemSchema = self ::getTypeFromClass ($ arrayItemType );
7497 }
7598
7699 $ props [$ prop ] = JsonSchema::array ($ arrayItemSchema );
77100 } else {
78- $ props [$ prop ] = JsonSchema:: typeRef ( self ::getTypeFromClass ($ type) );
101+ $ props [$ prop ] = self ::getTypeFromClass ($ type );
79102 }
80103
81104 if ($ isNullable ) {
82105 $ props [$ prop ] = JsonSchema::nullOr ($ props [$ prop ]);
83106 }
84107 }
85108
86- self ::$ __schema = JsonSchema::object ($ props );
109+ $ optionalProps = [];
110+ foreach (self ::__optionalProperties () as $ optProp ) {
111+ $ optionalProps [$ optProp ] = $ props [$ optProp ];
112+ unset($ props [$ optProp ]);
113+ }
114+
115+ self ::$ __schema = JsonSchema::object ($ props , $ optionalProps );
87116 }
88117
89118 return self ::$ __schema ;
@@ -94,19 +123,9 @@ private static function convertClassToTypeName(string $class): string
94123 return \substr (\strrchr ($ class , '\\' ), 1 );
95124 }
96125
97- private static function getTypeFromClass (string $ classOrType ): string
126+ private static function getTypeFromClass (string $ classOrType ): Type
98127 {
99- if (! \class_exists ($ classOrType )) {
100- return $ classOrType ;
101- }
102-
103- $ refObj = new \ReflectionClass ($ classOrType );
104-
105- if ($ refObj ->implementsInterface (ImmutableRecord::class)) {
106- return \call_user_func ([$ classOrType , '__type ' ]);
107- }
108-
109- return self ::convertClassToTypeName ($ classOrType );
128+ return TypeDetector::getTypeFromClass ($ classOrType , self ::__allowNestedSchema ());
110129 }
111130
112131 /**
0 commit comments