Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Commit 087b89f

Browse files
committed
add support for non-object schema reference
cover case with test
1 parent 65a28b7 commit 087b89f

File tree

10 files changed

+74
-83
lines changed

10 files changed

+74
-83
lines changed

src/lib/AttributeResolver.php

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,11 @@ protected function resolveProperty(PropertySchema $property, bool $isRequired):v
205205
}
206206

207207
$fkProperty = $property->getTargetProperty();
208+
if (!$fkProperty && !$property->getRefSchema()->isObjectSchema()) {
209+
$this->resolvePropertyRef($property, $attribute);
210+
return;
211+
}
208212
if (!$fkProperty) {
209-
210-
throw new InvalidDefinitionException(VarDumper::dumpAsString([
211-
$property->getName(),
212-
$property->isRefPointerToSelf(),
213-
$property->isRefPointerToProperty(),
214-
$property->getTargetPropertyName(),
215-
$property->getRefSchemaName(),
216-
$this->schema->getPropertyNames(),
217-
$property->getRefSchema()
218-
]));
219213
return;
220214
}
221215
$relatedClassName = $property->getRefClassName();
@@ -399,4 +393,28 @@ protected function prepareIndexes(array $indexes):array
399393
}
400394
return $dbIndexes;
401395
}
396+
397+
/**
398+
* @param \cebe\yii2openapi\lib\openapi\PropertySchema $property
399+
* @param \cebe\yii2openapi\lib\items\Attribute $attribute
400+
* @return void
401+
* @throws \yii\base\InvalidConfigException
402+
*/
403+
protected function resolvePropertyRef(PropertySchema $property, Attribute $attribute):void
404+
{
405+
$fkProperty = new PropertySchema(
406+
$property->getRefSchema()->getSchema(),
407+
$property->getName(),
408+
$this->schema
409+
);
410+
[$min, $max] = $fkProperty->guessMinMax();
411+
$attribute->setPhpType($fkProperty->guessPhpType())
412+
->setDbType($fkProperty->guessDbType(true))
413+
->setSize($fkProperty->getMaxLength())
414+
->setDescription($fkProperty->getAttr('description'))
415+
->setDefault($fkProperty->guessDefault())
416+
->setLimits($min, $max, $fkProperty->getMinLength());
417+
$this->attributes[$property->getName()] =
418+
$attribute->setFakerStub($this->guessFakerStub($attribute, $fkProperty));
419+
}
402420
}

src/lib/openapi/ComponentSchema.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,4 @@ public function getProperties():Generator
160160
yield Yii::createObject(PropertySchema::class, [$property, $name, $this]);
161161
}
162162
}
163-
164-
public function getPropertyNames():array
165-
{
166-
$names = [];
167-
foreach ($this->schema->properties as $name => $property) {
168-
$names[] = $name;
169-
}
170-
return $names;
171-
}
172163
}

src/lib/openapi/PropertySchema.php

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ class PropertySchema
4747
/**@var \cebe\yii2openapi\lib\openapi\ComponentSchema $refSchema * */
4848
private $refSchema;
4949

50-
/**@var string|null **/
51-
private $targetProperty = null;
52-
5350
/**
5451
* @var bool
5552
*/
@@ -64,6 +61,7 @@ class PropertySchema
6461
* @param \cebe\openapi\SpecObjectInterface $property
6562
* @param string $name
6663
* @param \cebe\yii2openapi\lib\openapi\ComponentSchema $schema
64+
* @throws \cebe\yii2openapi\lib\exceptions\InvalidDefinitionException
6765
* @throws \yii\base\InvalidConfigException
6866
*/
6967
public function __construct(SpecObjectInterface $property, string $name, ComponentSchema $schema)
@@ -92,17 +90,9 @@ private function initReference():void
9290
{
9391
$this->isReference = true;
9492
$this->refPointer = $this->property->getJsonReference()->getJsonPointer()->getPointer();
95-
$refSchemaName = \str_replace(self::REFERENCE_PATH, '', $this->refPointer);
93+
$refSchemaName = $this->getRefSchemaName();
9694
if ($this->isRefPointerToSelf()) {
9795
$this->refSchema = $this->schema;
98-
}elseif ($this->isRefPointerToProperty()) {
99-
$this->property->getContext()->mode = ReferenceContext::RESOLVE_MODE_INLINE;
100-
$pattern = '~^'.self::REFERENCE_PATH.'(?<schemaName>.+)/properties/(?<propName>.+)$~';
101-
if (!\preg_match($pattern, $this->refPointer, $matches)) {
102-
throw new InvalidDefinitionException('Invalid schema reference');
103-
}
104-
$this->targetProperty = $matches['propName'];
105-
$this->refSchema = Yii::createObject(ComponentSchema::class, [$this->property->resolve(), $matches['schemaName']]);
10696
} elseif ($this->isRefPointerToSchema()) {
10797
$this->property->getContext()->mode = ReferenceContext::RESOLVE_MODE_ALL;
10898
$this->refSchema = Yii::createObject(ComponentSchema::class, [$this->property->resolve(), $refSchemaName]);
@@ -123,18 +113,9 @@ private function initItemsReference():void
123113
$this->refPointer = $items->getJsonReference()->getJsonPointer()->getPointer();
124114
if ($this->isRefPointerToSelf()) {
125115
$this->refSchema = $this->schema;
126-
} elseif ($this->isRefPointerToProperty()) {
127-
$items->getContext()->mode = ReferenceContext::RESOLVE_MODE_ALL;
128-
$pattern = '~^'.self::REFERENCE_PATH.'(?<schemaName>.+)/properties/(?<propName>.+)$~';
129-
if (!\preg_match($pattern, $this->refPointer, $matches)) {
130-
throw new InvalidDefinitionException('Invalid schema reference');
131-
}
132-
$this->targetProperty = $matches['propName'];
133-
$this->refSchema = Yii::createObject(ComponentSchema::class, [$items->resolve(), $matches['schemaName']]);
134116
} elseif ($this->isRefPointerToSchema()) {
135117
$items->getContext()->mode = ReferenceContext::RESOLVE_MODE_ALL;
136-
$schemaName = \str_replace(self::REFERENCE_PATH, '', $this->refPointer);
137-
$this->refSchema = Yii::createObject(ComponentSchema::class, [$items->resolve(), $schemaName]);
118+
$this->refSchema = Yii::createObject(ComponentSchema::class, [$items->resolve(), $this->getRefSchemaName()]);
138119
}
139120
}
140121

@@ -176,17 +157,9 @@ public function getRefSchema():ComponentSchema
176157
*/
177158
public function getTargetProperty():?PropertySchema
178159
{
179-
if ($this->targetProperty !== null && $this->isRefPointerToProperty()) {
180-
return $this->getRefSchema()->getProperty($this->targetProperty);
181-
}
182160
return $this->getRefSchema()->getProperty($this->getRefSchema()->getPkName());
183161
}
184162

185-
public function getTargetPropertyName():?string
186-
{
187-
return $this->targetProperty;
188-
}
189-
190163
/**
191164
* @throws \yii\base\InvalidConfigException
192165
*/
@@ -215,13 +188,6 @@ public function isRefPointerToSelf():bool
215188
&& strpos($this->refPointer, '/properties/') !== false;
216189
}
217190

218-
public function isRefPointerToProperty():bool
219-
{
220-
return $this->isRefPointerToSchema()
221-
&& strpos($this->refPointer, '/' . $this->schema->getName() . '/') === false
222-
&& strpos($this->refPointer, '/properties/') !== false;
223-
}
224-
225191
public function getRefSchemaName():string
226192
{
227193
if (!$this->isReference && !$this->isItemsReference) {

tests/fixtures/non-db.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
'description' => 'Information about a user watching a Person',
3434
'isNotDb' => true,
3535
'attributes' => [
36+
'personId' => (new Attribute('personId', ['phpType' => 'string', 'dbType' => 'string']))
37+
->setReadOnly(false)->setRequired(false)->setDescription('The MongoDB Identifier'),
38+
'userId' => (new Attribute('userId', ['phpType' => 'string', 'dbType' => 'string']))
39+
->setReadOnly(false)->setRequired(false)->setDescription('The MongoDB Identifier'),
3640
'someProp' => (new Attribute('someProp', ['phpType' => 'int', 'dbType' => 'integer']))
3741
->setReadOnly(false)->setRequired(false)
3842
]

tests/specs/ref_noobject.yaml

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,19 @@ components:
3838
schemas:
3939
Mid:
4040
description: The MongoDB Identifier
41-
x-table: false
42-
type: object
43-
properties:
44-
mid:
45-
type: string
46-
x-faker: false
47-
x-db-type: false
48-
pattern: ^[0-9a-f]{24}$
41+
type: string
42+
x-faker: false
43+
x-db-type: false
44+
pattern: ^[0-9a-f]{24}$
4945
PersonWatch:
5046
description: Information about a user watching a Person
5147
type: object
5248
x-table: false
5349
properties:
5450
personId:
55-
$ref: "#/components/schemas/Mid/properties/mid"
51+
$ref: "#/components/schemas/Mid"
5652
userId:
57-
$ref: "#/components/schemas/Mid/properties/mid"
53+
$ref: "#/components/schemas/Mid"
5854
someProp:
5955
type: integer
6056
x-faker: false
Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
11
<?php
2-
32
namespace app\models\base;
43

4+
use yii\base\Model;
5+
56
/**
6-
* Information about a user watching a Person
7-
*
7+
* Information about a user watching a Person
88
*
99
*/
10-
abstract class PersonWatch extends \yii\db\ActiveRecord
10+
class PersonWatch extends Model
1111
{
12-
public static function tableName()
13-
{
14-
return '{{%person_watches}}';
15-
}
12+
/**
13+
* @var string The MongoDB Identifier
14+
*/
15+
public $personId;
16+
17+
/**
18+
* @var string The MongoDB Identifier
19+
*/
20+
public $userId;
21+
22+
/**
23+
* @var int
24+
*/
25+
public $someProp;
26+
1627

1728
public function rules()
1829
{
19-
return [];
30+
return [
31+
'trim' => [['personId', 'userId'], 'trim'],
32+
'personId_string' => [['personId'], 'string'],
33+
'userId_string' => [['userId'], 'string'],
34+
'someProp_integer' => [['someProp'], 'integer'],
35+
];
2036
}
2137
}

tests/unit/ComponentSchemaTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public function testWithoutReference()
1515
{
1616
$schemaFile = Yii::getAlias("@specs/blog.yaml");
1717
$openApi = Reader::readFromYamlFile($schemaFile, OpenApi::class, false);
18-
$schema = new ComponentSchema($openApi->components->schemas['User']);
18+
$schema = new ComponentSchema($openApi->components->schemas['User'], 'User');
1919
self::assertFalse($schema->isReference());
2020
self::assertTrue($schema->isObjectSchema());
2121
self::assertTrue($schema->hasProperties());
@@ -33,7 +33,7 @@ public function testByReference()
3333
{
3434
$schemaFile = Yii::getAlias("@specs/blog.yaml");
3535
$openApi = Reader::readFromYamlFile($schemaFile, OpenApi::class, false);
36-
$schema = new ComponentSchema($openApi->components->schemas['Post']->properties['category']);
36+
$schema = new ComponentSchema($openApi->components->schemas['Post']->properties['category'], 'Category');
3737
self::assertTrue($schema->isObjectSchema());
3838
self::assertEquals('id', $schema->getPkName());
3939
self::assertTrue($schema->isReference());

tests/unit/FakerStubResolverTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public function dataProvider()
2828
$schemaFile = Yii::getAlias("@specs/blog.yaml");
2929
$openApi = Reader::readFromYamlFile($schemaFile, OpenApi::class, false);
3030
$openApiSchema = $openApi->components->schemas['Fakerable'];
31-
$schema = new ComponentSchema($openApiSchema);
31+
$schema = new ComponentSchema($openApiSchema, 'Fakerable');
3232
return [
3333
[
3434
(new Attribute('id'))->setPhpType('int')->setDbType(YiiDbSchema::TYPE_BIGPK),

tests/unit/GeneratorTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public function provideTestcases()
1616
$tests = FileHelper::findFiles(Yii::getAlias('@specs'), ['recursive' => false, 'only' => ['*.php']]);
1717
$ret = [];
1818
foreach ($tests as $testFile) {
19-
if(!StringHelper::endsWith($testFile, 'ref_noobject.php')){
20-
continue;
21-
}
19+
// if(!StringHelper::endsWith($testFile, 'ref_noobject.php')){
20+
// continue;
21+
// }
2222
$ret[] = [substr($testFile, strlen(Yii::getAlias('@specs')) + 1)];
2323
}
2424
return $ret;

tests/unit/PropertySchemaTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public function testSelfReferencedProperty()
107107
{
108108
$schemaFile = Yii::getAlias("@specs/menu.yaml");
109109
$openApi = Reader::readFromYamlFile($schemaFile, OpenApi::class, false);
110-
$schema = new ComponentSchema($openApi->components->schemas['Menu']);
110+
$schema = new ComponentSchema($openApi->components->schemas['Menu'], 'Menu');
111111

112112
$prop = $schema->getProperty('parent');
113113
self::assertFalse($prop->isPrimaryKey());
@@ -155,6 +155,6 @@ private function getSchema():ComponentSchema
155155
{
156156
$schemaFile = Yii::getAlias("@specs/blog.yaml");
157157
$openApi = Reader::readFromYamlFile($schemaFile, OpenApi::class, false);
158-
return new ComponentSchema($openApi->components->schemas['Post']);
158+
return new ComponentSchema($openApi->components->schemas['Post'], 'Post');
159159
}
160160
}

0 commit comments

Comments
 (0)