Skip to content

Commit e3eb630

Browse files
committed
Add XML mapping for "encrypt" tag
1 parent 744f456 commit e3eb630

File tree

5 files changed

+122
-0
lines changed

5 files changed

+122
-0
lines changed

doctrine-mongo-mapping.xsd

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
<xs:choice minOccurs="0" maxOccurs="unbounded">
9191
<xs:element name="id" type="odm:id" minOccurs="0" />
9292
<xs:element name="field" type="odm:field" minOccurs="0" maxOccurs="unbounded" />
93+
<xs:element name="encrypt" type="odm:encrypt-field" minOccurs="0" maxOccurs="1" />
9394
<xs:element name="embed-one" type="odm:embed-one" minOccurs="0" maxOccurs="unbounded" />
9495
<xs:element name="embed-many" type="odm:embed-many" minOccurs="0" maxOccurs="unbounded" />
9596
<xs:element name="reference-one" type="odm:reference-one" minOccurs="0" maxOccurs="unbounded" />
@@ -128,7 +129,31 @@
128129
<xs:attribute name="mode" type="odm:read-preference-values" />
129130
</xs:complexType>
130131

132+
<xs:complexType name="encrypt-field">
133+
<xs:attribute name="queryType">
134+
<xs:simpleType>
135+
<xs:restriction base="xs:string">
136+
<xs:enumeration value="equality" />
137+
<xs:enumeration value="range" />
138+
</xs:restriction>
139+
</xs:simpleType>
140+
</xs:attribute>
141+
<xs:attribute name="min" type="xs:string" />
142+
<xs:attribute name="max" type="xs:string" />
143+
<xs:attribute name="sparsity" type="xs:integer" />
144+
<xs:attribute name="prevision" type="xs:integer" />
145+
<xs:attribute name="trimFactor" type="xs:integer" />
146+
<xs:attribute name="contention" type="xs:integer" />
147+
</xs:complexType>
148+
149+
<xs:complexType name="encrypt-embedded-document">
150+
</xs:complexType>
151+
131152
<xs:complexType name="field">
153+
<xs:choice minOccurs="0" maxOccurs="unbounded">
154+
<xs:element name="encrypt" type="odm:encrypt-field" minOccurs="0" maxOccurs="1" />
155+
</xs:choice>
156+
132157
<xs:attribute name="name" type="xs:NMTOKEN" />
133158
<xs:attribute name="type" type="xs:NMTOKEN" />
134159
<xs:attribute name="strategy" type="odm:storage-strategy" default="set" />

lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ public function loadMetadataForClass($className, \Doctrine\Persistence\Mapping\C
9898
$metadata->isMappedSuperclass = true;
9999
} elseif ($xmlRoot->getName() === 'embedded-document') {
100100
$metadata->isEmbeddedDocument = true;
101+
if (isset($xmlRoot->encrypt)) {
102+
$metadata->isEncrypted = true;
103+
}
101104
} elseif ($xmlRoot->getName() === 'query-result-document') {
102105
$metadata->isQueryResultDocument = true;
103106
} elseif ($xmlRoot->getName() === 'view') {
@@ -307,6 +310,30 @@ public function loadMetadataForClass($className, \Doctrine\Persistence\Mapping\C
307310
$mapping['lock'] = ((string) $attributes['lock'] === 'true');
308311
}
309312

313+
if (isset($field->encrypt)) {
314+
$mapping['encrypt'] = [];
315+
foreach ($field->encrypt->attributes() as $encryptKey => $encryptValue) {
316+
switch ($encryptKey) {
317+
case 'queryType':
318+
$mapping['encrypt'][$encryptKey] = (string) $encryptValue;
319+
break;
320+
case 'min':
321+
case 'max':
322+
$mapping['encrypt'][$encryptKey] = match ($mapping['type']) {
323+
'int' => (int) $encryptValue,
324+
'string' => (string) $encryptValue,
325+
};
326+
break;
327+
case 'sparsity':
328+
case 'prevision':
329+
case 'trimFactor':
330+
case 'contention':
331+
$mapping['encrypt'][$encryptKey] = (int) $encryptValue;
332+
break;
333+
}
334+
}
335+
}
336+
310337
$this->addFieldMapping($metadata, $mapping);
311338
}
312339
}

tests/Doctrine/ODM/MongoDB/Tests/Mapping/Driver/AbstractDriverTestCase.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
use Doctrine\Persistence\Mapping\Driver\MappingDriver;
99
use Documents\Account;
1010
use Documents\Address;
11+
use Documents\Encryption\ClientCard;
12+
use Documents\Encryption\PatientRecord;
1113
use Documents\Group;
1214
use Documents\Phonenumber;
1315
use Documents\Profile;
16+
use MongoDB\Driver\ClientEncryption;
1417
use PHPUnit\Framework\TestCase;
1518
use TestDocuments\EmbeddedDocument;
1619
use TestDocuments\NullableFieldsDocument;
@@ -521,4 +524,37 @@ public function testNullableFieldsMapping(): void
521524
'storeEmptyArray' => false,
522525
], $classMetadata->fieldMappings['groups']);
523526
}
527+
528+
public function testEncryptFieldMapping(): void
529+
{
530+
$classMetadata = new ClassMetadata(PatientRecord::class);
531+
$this->driver->loadMetadataForClass(PatientRecord::class, $classMetadata);
532+
533+
self::assertFalse($classMetadata->isEncrypted);
534+
535+
self::assertSame([
536+
'queryType' => ClientEncryption::QUERY_TYPE_EQUALITY,
537+
], $classMetadata->fieldMappings['ssn']['encrypt']);
538+
539+
self::assertSame([], $classMetadata->fieldMappings['billing']['encrypt']);
540+
541+
self::assertSame([
542+
'queryType' => ClientEncryption::QUERY_TYPE_RANGE,
543+
'sparsity' => 1,
544+
'trimFactor' => 4,
545+
'min' => 100,
546+
'max' => 2000,
547+
], $classMetadata->fieldMappings['billingAmount']['encrypt']);
548+
}
549+
550+
public function testEncryptEmbeddedDocumentMapping(): void
551+
{
552+
$classMetadata = new ClassMetadata(ClientCard::class);
553+
$this->driver->loadMetadataForClass(ClientCard::class, $classMetadata);
554+
555+
self::assertTrue($classMetadata->isEncrypted);
556+
557+
self::assertArrayNotHasKey('encrypt', $classMetadata->fieldMappings['type']);
558+
self::assertArrayNotHasKey('encrypt', $classMetadata->fieldMappings['number']);
559+
}
524560
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
6+
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
7+
8+
<embedded-document name="Documents\Encryption\ClientCard">
9+
<encrypt/>
10+
<field name="type" type="string"/>
11+
<field name="number" type="string"/>
12+
</embedded-document>
13+
14+
</doctrine-mongo-mapping>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<doctrine-mongo-mapping xmlns="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping
6+
http://doctrine-project.org/schemas/odm/doctrine-mongo-mapping.xsd">
7+
8+
<embedded-document name="Documents\Encryption\PatientRecord">
9+
<field name="ssn" type="string">
10+
<encrypt queryType="equality"/>
11+
</field>
12+
<field name="billing" type="string">
13+
<encrypt/>
14+
</field>
15+
<field name="billingAmount" type="int">
16+
<encrypt queryType="range" sparsity="1" trimFactor="4" min="100" max="2000" />
17+
</field>
18+
</embedded-document>
19+
20+
</doctrine-mongo-mapping>

0 commit comments

Comments
 (0)