Skip to content

Commit cf63d4d

Browse files
Pavel AlexeevPavel Alexeev
Pavel Alexeev
authored and
Pavel Alexeev
committed
php-kafka#33 Major refactor with PhpClassPropertyType typing
1 parent f770360 commit cf63d4d

18 files changed

+558
-59
lines changed

example/classes_minimal/EpamRole.php

+226
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
<?php
2+
3+
/**
4+
* Inheritance: no
5+
* Variants: no
6+
7+
8+
Fields Summary:
9+
- code [input]
10+
- name [input]
11+
- fullName [input]
12+
- masterSystem [multiselect]
13+
- roleSubject [select]
14+
- roleObject [multiselect]
15+
- topic [multiselect]
16+
- description [textarea]
17+
*/
18+
19+
namespace PhpKafka\PhpAvroSchemaGenerator\Example\Minimal;
20+
21+
/**
22+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing getList()
23+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByCode($value, $limit = 0, $offset = 0, $objectTypes = null)
24+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByName($value, $limit = 0, $offset = 0, $objectTypes = null)
25+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByFullName($value, $limit = 0, $offset = 0, $objectTypes = null)
26+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByMasterSystem($value, $limit = 0, $offset = 0, $objectTypes = null)
27+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByRoleSubject($value, $limit = 0, $offset = 0, $objectTypes = null)
28+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByRoleObject($value, $limit = 0, $offset = 0, $objectTypes = null)
29+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByTopic($value, $limit = 0, $offset = 0, $objectTypes = null)
30+
* @method static \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole\Listing|\PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole|null getByDescription($value, $limit = 0, $offset = 0, $objectTypes = null)
31+
*/
32+
33+
class EpamRole {
34+
protected $o_classId = "6";
35+
protected $o_className = "EpamRole";
36+
protected $code;
37+
protected $name;
38+
protected $fullName;
39+
/**
40+
* @var string[]
41+
**/
42+
protected $masterSystem;
43+
protected $roleSubject;
44+
protected $roleObject;
45+
protected $topic;
46+
protected $description;
47+
48+
49+
/**
50+
* @param array $values
51+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
52+
*/
53+
public static function create($values = array()) {
54+
$object = new static();
55+
return $object;
56+
}
57+
58+
/**
59+
* Get code - code
60+
* @return string|null
61+
*/
62+
public function getCode(): ?string
63+
{
64+
return $this->code;
65+
}
66+
67+
/**
68+
* Set code - code
69+
* @param string|null $code
70+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
71+
*/
72+
public function setCode(?string $code)
73+
{
74+
$this->code = $code;
75+
76+
return $this;
77+
}
78+
79+
/**
80+
* Get name - name
81+
* @return string|null
82+
*/
83+
public function getName(): ?string
84+
{
85+
return $this->name;
86+
}
87+
88+
/**
89+
* Set name - name
90+
* @param string|null $name
91+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
92+
*/
93+
public function setName(?string $name)
94+
{
95+
$this->name = $name;
96+
97+
return $this;
98+
}
99+
100+
/**
101+
* Get fullName - fullName
102+
* @return string|null
103+
*/
104+
public function getFullName(): ?string
105+
{
106+
return $this->fullName;
107+
}
108+
109+
/**
110+
* Set fullName - fullName
111+
* @param string|null $fullName
112+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
113+
*/
114+
public function setFullName(?string $fullName)
115+
{
116+
$this->fullName = $fullName;
117+
118+
return $this;
119+
}
120+
121+
/**
122+
* Get masterSystem - masterSystem
123+
* @return string[]|null
124+
*/
125+
public function getMasterSystem(): ?array
126+
{
127+
$data = $this->masterSystem;
128+
return $data;
129+
}
130+
131+
/**
132+
* Set masterSystem - masterSystem
133+
* @param string[]|null $masterSystem
134+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
135+
*/
136+
public function setMasterSystem(?array $masterSystem)
137+
{
138+
$this->masterSystem = $masterSystem;
139+
return $this;
140+
}
141+
142+
/**
143+
* Get roleSubject - subject
144+
* @return string|null
145+
*/
146+
public function getRoleSubject(): ?string
147+
{
148+
$data = $this->roleSubject;
149+
return $data;
150+
}
151+
152+
/**
153+
* Set roleSubject - subject
154+
* @param string|null $roleSubject
155+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
156+
*/
157+
public function setRoleSubject(?string $roleSubject)
158+
{
159+
$this->roleSubject = $roleSubject;
160+
return $this;
161+
}
162+
163+
/**
164+
* Get roleObject - roleObject
165+
* @return string[]|null
166+
*/
167+
public function getRoleObject(): ?array
168+
{
169+
$data = $this->roleObject;
170+
return $data;
171+
}
172+
173+
/**
174+
* Set roleObject - roleObject
175+
* @param string[]|null $roleObject
176+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
177+
*/
178+
public function setRoleObject(?array $roleObject)
179+
{
180+
$this->roleObject = $roleObject;
181+
return $this;
182+
}
183+
184+
/**
185+
* Get topic - topic
186+
* @return string[]|null
187+
*/
188+
public function getTopic(): ?array
189+
{
190+
$data = $this->topic;
191+
return $data;
192+
}
193+
194+
/**
195+
* Set topic - topic
196+
* @param string[]|null $topic
197+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
198+
*/
199+
public function setTopic(?array $topic)
200+
{
201+
$this->topic = $topic;
202+
return $this;
203+
}
204+
205+
/**
206+
* Get description - description
207+
* @return string|null
208+
*/
209+
public function getDescription(): ?string
210+
{
211+
$data = $this->description;
212+
return $data;
213+
}
214+
215+
/**
216+
* Set description - description
217+
* @param string|null $description
218+
* @return \PhpKafka\PhpAvroSchemaGenerator\Example\Minimal\EpamRole
219+
*/
220+
public function setDescription(?string $description)
221+
{
222+
$this->description = $description;
223+
return $this;
224+
}
225+
226+
}

src/Converter/PhpClassConverter.php

+11-12
Original file line numberDiff line numberDiff line change
@@ -67,16 +67,15 @@ public function convert(string $phpClass): ?PhpClassInterface
6767
* @param PhpClassPropertyInterface[] $properties
6868
* @return PhpClassPropertyInterface[]
6969
*/
70-
private function getConvertedProperties(array $properties): array
70+
protected function getConvertedProperties(array $properties): array
7171
{
7272
$convertedProperties = [];
7373
foreach ($properties as $property) {
74-
if (false === is_string($property->getPropertyType())) {
75-
continue;
74+
$convertedType = $property->getPropertyType();
75+
if (is_string($convertedType)) {
76+
$convertedType = $this->getConvertedType($property->getPropertyType());
7677
}
7778

78-
$convertedType = $this->getConvertedType($property->getPropertyType());
79-
8079
if (null === $convertedType) {
8180
continue;
8281
}
@@ -97,7 +96,7 @@ private function getConvertedProperties(array $properties): array
9796
* @param string $type
9897
* @return string|string[]|null
9998
*/
100-
private function getConvertedType(string $type)
99+
protected function getConvertedType(string $type)
101100
{
102101
$types = explode('|', $type);
103102

@@ -143,7 +142,7 @@ private function getFullTypeName(string $type, bool $isUnionType = false): ?stri
143142
* @param string[] $types
144143
* @return array<int,mixed>
145144
*/
146-
private function getConvertedUnionType(array $types): array
145+
protected function getConvertedUnionType(array $types): array
147146
{
148147
$convertedUnionType = [];
149148

@@ -168,7 +167,7 @@ private function getConvertedUnionType(array $types): array
168167
* @param string[] $types
169168
* @return string[]
170169
*/
171-
private function getArrayType(array $types): array
170+
protected function getArrayType(array $types): array
172171
{
173172
$itemPrefix = '[';
174173
$itemSuffix = ']';
@@ -200,7 +199,7 @@ private function getArrayType(array $types): array
200199
* @param string[] $types
201200
* @return string[]
202201
*/
203-
private function getArrayTypes(array $types): array
202+
protected function getArrayTypes(array $types): array
204203
{
205204
$arrayTypes = [];
206205

@@ -217,7 +216,7 @@ private function getArrayTypes(array $types): array
217216
* @param string[] $arrayTypes
218217
* @return string[]
219218
*/
220-
private function getCleanedArrayTypes(array $arrayTypes): array
219+
protected function getCleanedArrayTypes(array $arrayTypes): array
221220
{
222221
foreach ($arrayTypes as $idx => $arrayType) {
223222
if ('array' === $arrayType) {
@@ -238,7 +237,7 @@ private function getCleanedArrayTypes(array $arrayTypes): array
238237
return $arrayTypes;
239238
}
240239

241-
private function isArrayType(string $type): bool
240+
protected function isArrayType(string $type): bool
242241
{
243242
if ('array' === $type || str_contains($type, '[]')) {
244243
return true;
@@ -247,7 +246,7 @@ private function isArrayType(string $type): bool
247246
return false;
248247
}
249248

250-
private function convertNamespace(string $namespace): string
249+
protected function convertNamespace(string $namespace): string
251250
{
252251
return str_replace('\\', '.', $namespace);
253252
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace PhpKafka\PhpAvroSchemaGenerator\Exception;
4+
5+
class SchemaGeneratorException extends \Exception
6+
{
7+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace PhpKafka\PhpAvroSchemaGenerator\Exception;
4+
5+
class SkipPropertyException extends \Exception {
6+
7+
}

src/Generator/SchemaGenerator.php

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpKafka\PhpAvroSchemaGenerator\Generator;
66

77
use PhpKafka\PhpAvroSchemaGenerator\Avro\Avro;
8+
use PhpKafka\PhpAvroSchemaGenerator\Exception\SchemaGeneratorException;
89
use PhpKafka\PhpAvroSchemaGenerator\PhpClass\PhpClassInterface;
910
use PhpKafka\PhpAvroSchemaGenerator\PhpClass\PhpClassPropertyInterface;
1011
use PhpKafka\PhpAvroSchemaGenerator\Registry\ClassRegistryInterface;
@@ -98,6 +99,7 @@ public function generate(): array
9899
/**
99100
* @param PhpClassPropertyInterface $property
100101
* @return array<string, mixed>
102+
* @throws SchemaGeneratorException
101103
*/
102104
private function getFieldForProperty(PhpClassPropertyInterface $property): array
103105
{
@@ -106,6 +108,9 @@ private function getFieldForProperty(PhpClassPropertyInterface $property): array
106108

107109
if (PhpClassPropertyInterface::NO_DEFAULT !== $property->getPropertyDefault()) {
108110
$field['default'] = $property->getPropertyDefault();
111+
if (null === $field['default'] and !$field['type']->isNullable()){
112+
throw new SchemaGeneratorException('Provided default value "null", but that type does not present as first possible in union (see https://avro.apache.org/docs/current/spec.html#Unions)!');
113+
}
109114
}
110115

111116
if (null !== $property->getPropertyDoc() && '' !== $property->getPropertyDoc()) {
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace PhpKafka\PhpAvroSchemaGenerator\Parser;
4+
5+
use PhpKafka\PhpAvroSchemaGenerator\Exception\SkipPropertyException;
6+
use PhpKafka\PhpAvroSchemaGenerator\Parser\ClassPropertyParser;
7+
use PhpKafka\PhpAvroSchemaGenerator\PhpClass\PhpClassProperty;
8+
use PhpKafka\PhpAvroSchemaGenerator\PhpClass\PhpClassPropertyInterface;
9+
use PhpKafka\PhpAvroSchemaGenerator\PhpClass\PhpClassPropertyType;
10+
use PhpKafka\PhpAvroSchemaGenerator\PhpClass\PhpClassPropertyTypeItem;
11+
12+
/**
13+
* We will skip transient and private properties like starting at 'o_', '_', 'omitMandatoryCheck', 'allLazyKeysMarkedAsLoaded'
14+
*/
15+
class AvroClassPropertyParser extends ClassPropertyParser {
16+
17+
/**
18+
* @throws SkipPropertyException
19+
*/
20+
public function parseProperty($property): PhpClassPropertyInterface {
21+
$prop = parent::parseProperty($property);
22+
if (str_starts_with($prop->getPropertyName(), 'o_') or str_starts_with($prop->getPropertyName(), '_')
23+
or in_array($prop->getPropertyName(), ['omitMandatoryCheck', 'allLazyKeysMarkedAsLoaded'])) {
24+
throw new SkipPropertyException();
25+
}
26+
// return $prop;
27+
$prop_ = new PhpClassProperty(
28+
$prop->getPropertyName(),
29+
// make type nullable. Can't now in array. See https://github.com/php-kafka/php-avro-schema-generator/issues/33#issuecomment-1007490595
30+
$prop->getPropertyType()->isNullable() ? $prop->getPropertyType() : new PhpClassPropertyType(new PhpClassPropertyTypeItem('null'), ...$prop->getPropertyType()->getTypeItems()),
31+
// 'null|' . $prop->getPropertyType(), // make type nullable // See https://github.com/php-kafka/php-avro-schema-generator/issues/33#issuecomment-1007551821
32+
// and only in string work. See https://github.com/php-kafka/php-avro-schema-generator/issues/33#issuecomment-1007490595
33+
($prop->getPropertyDefault() != PhpClassPropertyInterface::NO_DEFAULT ?: null),
34+
$prop->getPropertyDoc(),
35+
$prop->getPropertyLogicalType()
36+
);
37+
return $prop_;
38+
}
39+
}

0 commit comments

Comments
 (0)