Skip to content

Commit 50abcc0

Browse files
committed
Merge pull request #48 from rabbitby/master
Add MongoDB annotation generator
2 parents 9656fd2 + 6de776b commit 50abcc0

File tree

4 files changed

+297
-0
lines changed

4 files changed

+297
-0
lines changed
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
/*
4+
* (c) Kévin Dunglas <[email protected]>
5+
*
6+
* This source file is subject to the MIT license that is bundled
7+
* with this source code in the file LICENSE.
8+
*/
9+
10+
namespace ApiPlatform\SchemaGenerator\AnnotationGenerator;
11+
12+
use ApiPlatform\SchemaGenerator\CardinalitiesExtractor;
13+
use ApiPlatform\SchemaGenerator\TypesGenerator;
14+
15+
/**
16+
* Doctrine MongoDB annotation generator.
17+
*
18+
* @author Andrew Meshchanchuk <[email protected]>>
19+
*/
20+
class DoctrineMongoDBAnnotationGenerator extends AbstractAnnotationGenerator
21+
{
22+
/**
23+
* {@inheritdoc}
24+
*/
25+
public function generateClassAnnotations($className)
26+
{
27+
$class = $this->classes[$className];
28+
29+
if ($class['isEnum']) {
30+
return [];
31+
}
32+
33+
if (isset($this->config['types'][$class['resource']->localName()]['doctrine']['inheritanceMapping'])) {
34+
$inheritanceMapping = $this->config['types'][$class['resource']->localName()]['doctrine']['inheritanceMapping'];
35+
} else {
36+
$inheritanceMapping = $class['abstract'] ? '@MongoDB\MappedSuperclass' : '@MongoDB\Document';
37+
}
38+
39+
return [
40+
'',
41+
$inheritanceMapping,
42+
];
43+
}
44+
45+
/**
46+
* {@inheritdoc}
47+
*/
48+
public function generateFieldAnnotations($className, $fieldName)
49+
{
50+
$this->classes[$className];
51+
$field = $this->classes[$className]['fields'][$fieldName];
52+
53+
$annotations = [];
54+
55+
if ($field['isEnum']) {
56+
if ($field['isArray']) {
57+
$type = 'simple_array';
58+
} else {
59+
$type = 'string';
60+
}
61+
} else {
62+
switch ($field['range']) {
63+
case 'Boolean':
64+
$type = 'boolean';
65+
break;
66+
case 'Date':
67+
// No break
68+
case 'DateTime':
69+
$type = 'date';
70+
break;
71+
case 'Time':
72+
$type = 'time';
73+
break;
74+
case 'Number':
75+
// No break
76+
case 'Float':
77+
$type = 'float';
78+
break;
79+
case 'Integer':
80+
$type = 'integer';
81+
break;
82+
case 'Text':
83+
// No break
84+
case 'URL':
85+
$type = 'string';
86+
break;
87+
}
88+
}
89+
90+
if (isset($type)) {
91+
if (!$field['isId']) {
92+
$annotation = '@MongoDB\Field';
93+
94+
if ($field['isArray']) {
95+
$type = 'collection';
96+
}
97+
98+
$annotation .= sprintf('(type="%s")', $type);
99+
100+
$annotations[] = $annotation;
101+
}
102+
} else {
103+
if ($field['cardinality'] === CardinalitiesExtractor::CARDINALITY_0_1
104+
|| $field['cardinality'] === CardinalitiesExtractor::CARDINALITY_1_1
105+
|| $field['cardinality'] === CardinalitiesExtractor::CARDINALITY_N_0
106+
|| $field['cardinality'] === CardinalitiesExtractor::CARDINALITY_N_1) {
107+
$annotations[] = sprintf('@MongoDB\ReferenceOne(targetDocument="%s", simple=true))', $this->getRelationName($field['range']));
108+
} elseif ($field['cardinality'] === CardinalitiesExtractor::CARDINALITY_0_N
109+
|| $field['cardinality'] === CardinalitiesExtractor::CARDINALITY_1_N
110+
|| $field['cardinality'] === CardinalitiesExtractor::CARDINALITY_N_N) {
111+
$annotations[] = sprintf('@MongoDB\ReferenceMany(targetDocument="%s", simple=true)', $this->getRelationName($field['range']));
112+
}
113+
}
114+
115+
if ($field['isId']) {
116+
$annotations[] = '@MongoDB\Id';
117+
}
118+
119+
return $annotations;
120+
}
121+
122+
/**
123+
* {@inheritdoc}
124+
*/
125+
public function generateUses($className)
126+
{
127+
$resource = $this->classes[$className]['resource'];
128+
129+
$subClassOf = $resource->get('rdfs:subClassOf');
130+
$typeIsEnum = $subClassOf && $subClassOf->getUri() === TypesGenerator::SCHEMA_ORG_ENUMERATION;
131+
132+
return $typeIsEnum ? [] : ['Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB'];
133+
}
134+
135+
/**
136+
* Gets class or interface name to use in relations.
137+
*
138+
* @param string $range
139+
*
140+
* @return string
141+
*/
142+
private function getRelationName($range)
143+
{
144+
$class = $this->classes[$range];
145+
146+
if (isset($class['interfaceName'])) {
147+
return $class['interfaceName'];
148+
}
149+
150+
return $class['name'];
151+
}
152+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# The PHP namespace of generated entities
2+
namespaces:
3+
entity: 'AddressBook\Document'
4+
# Enable DunglasApiAnnotationGenerator
5+
annotationGenerators:
6+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\PhpDocAnnotationGenerator
7+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\DoctrineMongoDBAnnotationGenerator
8+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\ConstraintAnnotationGenerator
9+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\DunglasApiAnnotationGenerator
10+
# The list of types and properties we want to use
11+
types:
12+
Person:
13+
parent: false
14+
properties:
15+
name: ~
16+
familyName: ~
17+
givenName: ~
18+
additionalName: ~
19+
gender: ~
20+
address: { range: PostalAddress }
21+
birthDate: ~
22+
telephone: ~
23+
email: ~
24+
jobTitle: ~
25+
# Default relation table name would be "person_organization" for all following fields, but we customize them
26+
affiliation: ~
27+
brand: { relationTableName: "person_brand"}
28+
memberOf: { range: "Organization", cardinality: (1..*), relationTableName: "person_memberof"}
29+
worksFor: { range: "Organization", cardinality: (0..*), relationTableName: "person_worksfor"}
30+
# url field is a custom one without definition, it should render error
31+
url: ~
32+
friends: { range: "Person", cardinality: (0..*) }
33+
PostalAddress:
34+
# Disable the generation of the class hierarchy for this type
35+
parent: false
36+
properties:
37+
# Force the type of the addressCountry property to text
38+
addressCountry: { range: "Text" }
39+
addressLocality: ~
40+
addressRegion: ~
41+
postOfficeBoxNumber: ~
42+
postalCode: ~
43+
streetAddress: ~
44+
Organization:
45+
parent: false
46+
properties:
47+
name: ~

tests/config/mongodb/ecommerce.yml

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
header: |
2+
/*
3+
* This file is part of the Ecommerce package.
4+
*
5+
* (c) Kévin Dunglas <[email protected]>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
rdfa:
11+
-
12+
uri: tests/data/schema.rdfa
13+
format: rdfa
14+
relations:
15+
- tests/data/v1.owl
16+
namespaces:
17+
entity: 'Dunglas\EcommerceBundle\Document'
18+
enum: 'Dunglas\EcommerceBundle\Enum'
19+
interface: 'Dunglas\EcommerceBundle\Model'
20+
annotationGenerators:
21+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\PhpDocAnnotationGenerator
22+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\ConstraintAnnotationGenerator
23+
- ApiPlatform\SchemaGenerator\AnnotationGenerator\DoctrineMongoDBAnnotationGenerator
24+
author: "Kévin Dunglas <[email protected]>"
25+
debug: true
26+
useInterface: true
27+
checkIsGoodRelations: true
28+
types:
29+
Thing:
30+
properties:
31+
name: ~
32+
description: ~
33+
image: { range: ImageObject }
34+
additionalType: ~
35+
Product:
36+
properties:
37+
sku:
38+
cardinality: "(0..1)"
39+
url: ~
40+
brand: ~
41+
productID: ~
42+
releaseDate: ~
43+
offers: ~
44+
itemCondition: ~
45+
gtin13: ~
46+
gtin14: ~
47+
gtin8: ~
48+
mpn: ~
49+
color: ~
50+
depth: { range: "Text" }
51+
height: { range: "Text" }
52+
weight: { range: "Text" }
53+
width: { range: "Text" }
54+
seller: { range: "Seller" }
55+
Brand:
56+
parent: "Thing"
57+
properties:
58+
logo: { range: "ImageObject" }
59+
Seller:
60+
parent: false
61+
guessFrom: Person
62+
properties:
63+
name: ~
64+
birthDate: ~
65+
ImageObject:
66+
parent: Thing
67+
properties:
68+
caption: ~
69+
ProductModel:
70+
properties:
71+
isVariantOf: ~
72+
Offer:
73+
parent: Thing
74+
properties:
75+
acceptedPaymentMethod: ~
76+
availability: ~
77+
availabilityStarts: ~
78+
availabilityEnds: ~
79+
availableDeliveryMethod: ~
80+
category: { range: "Text" }
81+
deliveryLeadTime: ~
82+
inventoryLevel: ~
83+
itemCondition: ~
84+
price: { range: Number }
85+
priceCurrency: ~
86+
validFrom: ~
87+
validThrough: ~
88+
DeliveryChargeSpecification: { parent: false }
89+
PaymentChargeSpecification: { parent: false }
90+
OfferItemCondition: ~
91+
PaymentMethod: ~
92+
ItemAvailability: ~
93+
DeliveryMethod: ~
94+
QuantitativeValue: { parent: false }

tests/run-tests.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ bin/schema generate-types build/blog/ tests/config/blog.yml
1212
bin/schema generate-types build/ecommerce/ tests/config/ecommerce.yml
1313
bin/schema generate-types build/vgo/ tests/config/vgo.yml
1414

15+
mkdir -p build/mongodb/ecommerce/ build/mongodb/address-book/
16+
bin/schema generate-types build/mongodb/address-book/ tests/config/mongodb/address-book.yml
17+
bin/schema generate-types build/mongodb/ecommerce/ tests/config/mongodb/ecommerce.yml
18+
1519
# Check code CS
1620
vendor/bin/php-cs-fixer --dry-run --diff -vvv fix src/
1721

0 commit comments

Comments
 (0)