@@ -6020,4 +6020,322 @@ public function testCreateUpdateDocumentsMismatch(): void
60206020 }
60216021 $ database ->deleteCollection ($ colName );
60226022 }
6023+ public function testDecodeWithDifferentSelectionTypes (): void
6024+ {
6025+ /** @var Database $database */
6026+ $ database = static ::getDatabase ();
6027+
6028+ if (!$ database ->getAdapter ()->getSupportForRelationships ()) {
6029+ $ this ->expectNotToPerformAssertions ();
6030+ return ;
6031+ }
6032+
6033+ if (!$ database ->getAdapter ()->getSupportForSpatialAttributes ()) {
6034+ $ this ->expectNotToPerformAssertions ();
6035+ return ;
6036+ }
6037+
6038+ $ database ->addFilter (
6039+ 'encrypt ' ,
6040+ function (mixed $ value ) {
6041+ return json_encode ([
6042+ 'data ' => base64_encode ($ value ),
6043+ 'method ' => 'base64 ' ,
6044+ 'version ' => 'v1 ' ,
6045+ ]);
6046+ },
6047+ function (mixed $ value ) {
6048+ if (is_null ($ value )) {
6049+ return ;
6050+ }
6051+ $ value = json_decode ($ value , true );
6052+ return base64_decode ($ value ['data ' ]);
6053+ }
6054+ );
6055+
6056+ $ citiesId = 'TestCities ' ;
6057+ $ storesId = 'TestStores ' ;
6058+
6059+ $ database ->createCollection ($ citiesId );
6060+ $ database ->createCollection ($ storesId );
6061+
6062+ $ database ->createAttribute ($ citiesId , 'name ' , Database::VAR_STRING , 255 , required: true );
6063+ $ database ->createAttribute ($ citiesId , 'area ' , Database::VAR_POLYGON , 0 , required: true );
6064+ $ database ->createAttribute ($ citiesId , 'population ' , Database::VAR_INTEGER , 0 , required: false , default: 0 );
6065+ $ database ->createAttribute ($ citiesId , 'secretCode ' , Database::VAR_STRING , 255 , required: false , default: 'default-secret ' , filters: ['encrypt ' ]);
6066+ $ database ->createAttribute ($ citiesId , 'center ' , Database::VAR_POINT , 0 , required: false , default: [0.0 , 0.0 ]);
6067+
6068+ $ database ->createAttribute ($ storesId , 'name ' , Database::VAR_STRING , 255 , required: true );
6069+ $ database ->createAttribute ($ storesId , 'revenue ' , Database::VAR_FLOAT , 0 , required: false , default: 0.0 );
6070+ $ database ->createAttribute ($ storesId , 'location ' , Database::VAR_POINT , 0 , required: false , default: [1.0 , 1.0 ]);
6071+
6072+ $ database ->createRelationship (
6073+ collection: $ storesId ,
6074+ relatedCollection: $ citiesId ,
6075+ type: Database::RELATION_MANY_TO_ONE ,
6076+ twoWay: true ,
6077+ id: 'city ' ,
6078+ twoWayKey: 'stores '
6079+ );
6080+
6081+ $ cityDoc = new Document ([
6082+ '$id ' => 'city-1 ' ,
6083+ 'name ' => 'Test City ' ,
6084+ 'area ' => [[[40.7128 , -74.0060 ], [40.7589 , -74.0060 ], [40.7589 , -73.9851 ], [40.7128 , -73.9851 ], [40.7128 , -74.0060 ]]],
6085+ 'population ' => 1000000 ,
6086+ 'secretCode ' => 'super-secret-code ' ,
6087+ 'center ' => [40.7282 , -73.9942 ],
6088+ '$permissions ' => [Permission::read (Role::any ())],
6089+ ]);
6090+ $ createdCity = $ database ->createDocument ($ citiesId , $ cityDoc );
6091+
6092+ $ storeDoc = new Document ([
6093+ '$id ' => 'store-1 ' ,
6094+ 'name ' => 'Main Store ' ,
6095+ 'revenue ' => 50000.75 ,
6096+ 'location ' => [40.7300 , -73.9900 ],
6097+ 'city ' => $ createdCity ->getId (),
6098+ '$permissions ' => [Permission::read (Role::any ())],
6099+ ]);
6100+ $ createdStore = $ database ->createDocument ($ storesId , $ storeDoc );
6101+
6102+ $ cityWithSelection = $ database ->getDocument ($ citiesId , 'city-1 ' , [
6103+ Query::select (['name ' , 'population ' ])
6104+ ]);
6105+
6106+ $ this ->assertEquals ('Test City ' , $ cityWithSelection ->getAttribute ('name ' ));
6107+ $ this ->assertEquals (1000000 , $ cityWithSelection ->getAttribute ('population ' ));
6108+
6109+ $ this ->assertNull ($ cityWithSelection ->getAttribute ('area ' ));
6110+ $ this ->assertNull ($ cityWithSelection ->getAttribute ('secretCode ' ));
6111+ $ this ->assertNull ($ cityWithSelection ->getAttribute ('center ' ));
6112+
6113+ $ cityWithSpatial = $ database ->getDocument ($ citiesId , 'city-1 ' , [
6114+ Query::select (['name ' , 'area ' , 'center ' ])
6115+ ]);
6116+
6117+ $ this ->assertEquals ('Test City ' , $ cityWithSpatial ->getAttribute ('name ' ));
6118+ $ this ->assertNotNull ($ cityWithSpatial ->getAttribute ('area ' ));
6119+ $ this ->assertEquals ([[[40.7128 , -74.0060 ], [40.7589 , -74.0060 ], [40.7589 , -73.9851 ], [40.7128 , -73.9851 ], [40.7128 , -74.0060 ]]], $ cityWithSpatial ->getAttribute ('area ' ));
6120+ $ this ->assertEquals ([40.7282 , -73.9942 ], $ cityWithSpatial ->getAttribute ('center ' ));
6121+ // Null -> not selected
6122+ $ this ->assertNull ($ cityWithSpatial ->getAttribute ('population ' ));
6123+ $ this ->assertNull ($ cityWithSpatial ->getAttribute ('secretCode ' ));
6124+
6125+ $ cityWithEncrypted = $ database ->getDocument ($ citiesId , 'city-1 ' , [
6126+ Query::select (['name ' , 'secretCode ' ])
6127+ ]);
6128+
6129+ $ this ->assertEquals ('Test City ' , $ cityWithEncrypted ->getAttribute ('name ' ));
6130+ $ this ->assertEquals ('super-secret-code ' , $ cityWithEncrypted ->getAttribute ('secretCode ' )); // Should be decrypted
6131+
6132+ $ this ->assertNull ($ cityWithEncrypted ->getAttribute ('area ' ));
6133+ $ this ->assertNull ($ cityWithEncrypted ->getAttribute ('population ' ));
6134+
6135+ $ cityWithStores = $ database ->getDocument ($ citiesId , 'city-1 ' , [
6136+ Query::select (['stores.name ' ])
6137+ ]);
6138+
6139+ $ this ->assertNotNull ($ cityWithStores ->getAttribute ('stores ' ));
6140+ $ this ->assertCount (1 , $ cityWithStores ->getAttribute ('stores ' ));
6141+ $ this ->assertEquals ('Main Store ' , $ cityWithStores ->getAttribute ('stores ' )[0 ]['name ' ]);
6142+
6143+ $ this ->assertEquals ('super-secret-code ' , $ cityWithStores ->getAttribute ('secretCode ' ));
6144+ $ this ->assertNotNull ($ cityWithStores ->getAttribute ('area ' ));
6145+ $ this ->assertEquals ([40.7282 , -73.9942 ], $ cityWithStores ->getAttribute ('center ' ));
6146+
6147+ $ cityWithMultipleStoreFields = $ database ->getDocument ($ citiesId , 'city-1 ' , [
6148+ Query::select (['stores.name ' , 'stores.revenue ' ])
6149+ ]);
6150+
6151+ $ this ->assertNotNull ($ cityWithMultipleStoreFields ->getAttribute ('stores ' ));
6152+ $ this ->assertEquals ('Main Store ' , $ cityWithMultipleStoreFields ->getAttribute ('stores ' )[0 ]['name ' ]);
6153+ $ this ->assertEquals (50000.75 , $ cityWithMultipleStoreFields ->getAttribute ('stores ' )[0 ]['revenue ' ]);
6154+
6155+ $ this ->assertEquals ('super-secret-code ' , $ cityWithMultipleStoreFields ->getAttribute ('secretCode ' ));
6156+
6157+ $ cityWithMixed = $ database ->getDocument ($ citiesId , 'city-1 ' , [
6158+ Query::select (['name ' , 'population ' , 'stores.name ' ])
6159+ ]);
6160+
6161+ $ this ->assertEquals ('Test City ' , $ cityWithMixed ->getAttribute ('name ' ));
6162+ $ this ->assertEquals (1000000 , $ cityWithMixed ->getAttribute ('population ' ));
6163+
6164+ $ this ->assertNotNull ($ cityWithMixed ->getAttribute ('stores ' ));
6165+ $ this ->assertEquals ('Main Store ' , $ cityWithMixed ->getAttribute ('stores ' )[0 ]['name ' ]);
6166+
6167+ $ citiesWithStores = $ database ->find ($ citiesId , [
6168+ Query::select (['stores.name ' ]),
6169+ Query::equal ('$id ' , ['city-1 ' ])
6170+ ]);
6171+
6172+ $ this ->assertCount (1 , $ citiesWithStores );
6173+ $ city = $ citiesWithStores [0 ];
6174+ $ this ->assertNotNull ($ city ->getAttribute ('stores ' ));
6175+ $ this ->assertEquals ('Main Store ' , $ city ->getAttribute ('stores ' )[0 ]['name ' ]);
6176+ $ this ->assertEquals ('super-secret-code ' , $ city ->getAttribute ('secretCode ' ));
6177+
6178+ $ storeWithCityArea = $ database ->getDocument ($ storesId , 'store-1 ' , [
6179+ Query::select (['location ' ,'city.area ' ])
6180+ ]);
6181+
6182+ $ this ->assertNotNull ($ storeWithCityArea ->getAttribute ('city ' ));
6183+ $ this ->assertNotNull ($ storeWithCityArea ->getAttribute ('city ' )['area ' ]);
6184+ $ this ->assertEquals ([40.7300 , -73.9900 ], $ storeWithCityArea ->getAttribute ('location ' ));
6185+
6186+ $ database ->deleteCollection ($ citiesId );
6187+ $ database ->deleteCollection ($ storesId );
6188+ }
6189+
6190+ public function testDecodeWithoutRelationships (): void
6191+ {
6192+ /** @var Database $database */
6193+ $ database = static ::getDatabase ();
6194+
6195+ if (!$ database ->getAdapter ()->getSupportForSpatialAttributes ()) {
6196+ $ this ->expectNotToPerformAssertions ();
6197+ return ;
6198+ }
6199+
6200+ $ database ->addFilter (
6201+ 'encryptTest ' ,
6202+ function (mixed $ value ) {
6203+ return 'encrypted: ' . base64_encode ($ value );
6204+ },
6205+ function (mixed $ value ) {
6206+ if (is_null ($ value ) || !str_starts_with ($ value , 'encrypted: ' )) {
6207+ return $ value ;
6208+ }
6209+ return base64_decode (substr ($ value , 10 ));
6210+ }
6211+ );
6212+
6213+ $ collectionId = 'TestDecodeCollection ' ;
6214+ $ database ->createCollection ($ collectionId );
6215+
6216+ $ database ->createAttribute ($ collectionId , 'title ' , Database::VAR_STRING , 255 , required: true );
6217+ $ database ->createAttribute ($ collectionId , 'description ' , Database::VAR_STRING , 1000 , required: false , default: 'No description ' );
6218+ $ database ->createAttribute ($ collectionId , 'count ' , Database::VAR_INTEGER , 0 , required: false , default: 0 );
6219+ $ database ->createAttribute ($ collectionId , 'price ' , Database::VAR_FLOAT , 0 , required: false , default: 0.0 );
6220+ $ database ->createAttribute ($ collectionId , 'active ' , Database::VAR_BOOLEAN , 0 , required: false , default: true );
6221+ $ database ->createAttribute ($ collectionId , 'tags ' , Database::VAR_STRING , 50 , required: false , array: true );
6222+ $ database ->createAttribute ($ collectionId , 'secret ' , Database::VAR_STRING , 255 , required: false , default: 'default-secret ' , filters: ['encryptTest ' ]);
6223+ $ database ->createAttribute ($ collectionId , 'location ' , Database::VAR_POINT , 0 , required: false , default: [0.0 , 0.0 ]);
6224+ $ database ->createAttribute ($ collectionId , 'boundary ' , Database::VAR_POLYGON , 0 , required: false );
6225+
6226+ $ doc = new Document ([
6227+ '$id ' => 'test-1 ' ,
6228+ 'title ' => 'Test Document ' ,
6229+ 'description ' => 'This is a test document ' ,
6230+ 'count ' => 42 ,
6231+ 'price ' => 99.99 ,
6232+ 'active ' => true ,
6233+ 'tags ' => ['tag1 ' , 'tag2 ' , 'tag3 ' ],
6234+ 'secret ' => 'my-secret-value ' ,
6235+ 'location ' => [40.7128 , -74.0060 ],
6236+ 'boundary ' => [[[0 , 0 ], [0 , 1 ], [1 , 1 ], [1 , 0 ], [0 , 0 ]]],
6237+ '$permissions ' => [Permission::read (Role::any ())],
6238+ ]);
6239+ $ created = $ database ->createDocument ($ collectionId , $ doc );
6240+
6241+ $ selected = $ database ->getDocument ($ collectionId , 'test-1 ' , [
6242+ Query::select (['title ' , 'count ' , 'secret ' ])
6243+ ]);
6244+
6245+ $ this ->assertEquals ('Test Document ' , $ selected ->getAttribute ('title ' ));
6246+ $ this ->assertEquals (42 , $ selected ->getAttribute ('count ' ));
6247+ $ this ->assertEquals ('my-secret-value ' , $ selected ->getAttribute ('secret ' ));
6248+
6249+ $ this ->assertNull ($ selected ->getAttribute ('description ' ));
6250+ $ this ->assertNull ($ selected ->getAttribute ('price ' ));
6251+ $ this ->assertNull ($ selected ->getAttribute ('location ' ));
6252+
6253+ $ spatialSelected = $ database ->getDocument ($ collectionId , 'test-1 ' , [
6254+ Query::select (['title ' , 'location ' , 'boundary ' ])
6255+ ]);
6256+
6257+ $ this ->assertEquals ('Test Document ' , $ spatialSelected ->getAttribute ('title ' ));
6258+ $ this ->assertEquals ([40.7128 , -74.0060 ], $ spatialSelected ->getAttribute ('location ' ));
6259+ $ this ->assertEquals ([[[0 , 0 ], [0 , 1 ], [1 , 1 ], [1 , 0 ], [0 , 0 ]]], $ spatialSelected ->getAttribute ('boundary ' ));
6260+ $ this ->assertNull ($ spatialSelected ->getAttribute ('secret ' ));
6261+ $ this ->assertNull ($ spatialSelected ->getAttribute ('count ' ));
6262+
6263+ $ arraySelected = $ database ->getDocument ($ collectionId , 'test-1 ' , [
6264+ Query::select (['title ' , 'tags ' ])
6265+ ]);
6266+
6267+ $ this ->assertEquals ('Test Document ' , $ arraySelected ->getAttribute ('title ' ));
6268+ $ this ->assertEquals (['tag1 ' , 'tag2 ' , 'tag3 ' ], $ arraySelected ->getAttribute ('tags ' ));
6269+ $ this ->assertNull ($ arraySelected ->getAttribute ('active ' ));
6270+
6271+ $ allSelected = $ database ->getDocument ($ collectionId , 'test-1 ' , [
6272+ Query::select (['* ' ])
6273+ ]);
6274+
6275+ $ this ->assertEquals ('Test Document ' , $ allSelected ->getAttribute ('title ' ));
6276+ $ this ->assertEquals ('This is a test document ' , $ allSelected ->getAttribute ('description ' ));
6277+ $ this ->assertEquals (42 , $ allSelected ->getAttribute ('count ' ));
6278+ $ this ->assertEquals ('my-secret-value ' , $ allSelected ->getAttribute ('secret ' ));
6279+ $ this ->assertEquals ([40.7128 , -74.0060 ], $ allSelected ->getAttribute ('location ' ));
6280+
6281+ $ noSelection = $ database ->getDocument ($ collectionId , 'test-1 ' );
6282+
6283+ $ this ->assertEquals ('Test Document ' , $ noSelection ->getAttribute ('title ' ));
6284+ $ this ->assertEquals ('This is a test document ' , $ noSelection ->getAttribute ('description ' ));
6285+ $ this ->assertEquals ('my-secret-value ' , $ noSelection ->getAttribute ('secret ' ));
6286+ $ this ->assertEquals ([40.7128 , -74.0060 ], $ noSelection ->getAttribute ('location ' ));
6287+
6288+ $ database ->deleteCollection ($ collectionId );
6289+ }
6290+
6291+ public function testDecodeWithMultipleFilters (): void
6292+ {
6293+ /** @var Database $database */
6294+ $ database = static ::getDatabase ();
6295+
6296+ $ database ->addFilter (
6297+ 'upperCase ' ,
6298+ function (mixed $ value ) { return strtoupper ($ value ); },
6299+ function (mixed $ value ) { return strtolower ($ value ); }
6300+ );
6301+
6302+ $ database ->addFilter (
6303+ 'prefix ' ,
6304+ function (mixed $ value ) { return 'prefix_ ' . $ value ; },
6305+ function (mixed $ value ) { return str_replace ('prefix_ ' , '' , $ value ); }
6306+ );
6307+
6308+ $ collectionId = 'EdgeCaseCollection ' ;
6309+ $ database ->createCollection ($ collectionId );
6310+
6311+ $ database ->createAttribute ($ collectionId , 'name ' , Database::VAR_STRING , 255 , required: true );
6312+ $ database ->createAttribute ($ collectionId , 'processedName ' , Database::VAR_STRING , 255 , required: false , filters: ['upperCase ' , 'prefix ' ]);
6313+ $ database ->createAttribute ($ collectionId , 'nullableField ' , Database::VAR_STRING , 255 , required: false );
6314+
6315+ $ doc = new Document ([
6316+ '$id ' => 'edge-1 ' ,
6317+ 'name ' => 'Test Name ' ,
6318+ 'processedName ' => 'test value ' ,
6319+ 'nullableField ' => null ,
6320+ '$permissions ' => [Permission::read (Role::any ())],
6321+ ]);
6322+ $ created = $ database ->createDocument ($ collectionId , $ doc );
6323+
6324+ $ selected = $ database ->getDocument ($ collectionId , 'edge-1 ' , [
6325+ Query::select (['name ' , 'processedName ' ])
6326+ ]);
6327+
6328+ $ this ->assertEquals ('Test Name ' , $ selected ->getAttribute ('name ' ));
6329+ $ this ->assertEquals ('test value ' , $ selected ->getAttribute ('processedName ' ));
6330+ $ this ->assertNull ($ selected ->getAttribute ('nullableField ' ));
6331+
6332+ $ nullSelected = $ database ->getDocument ($ collectionId , 'edge-1 ' , [
6333+ Query::select (['name ' , 'nullableField ' ])
6334+ ]);
6335+
6336+ $ this ->assertEquals ('Test Name ' , $ nullSelected ->getAttribute ('name ' ));
6337+ $ this ->assertNull ($ nullSelected ->getAttribute ('nullableField ' ));
6338+
6339+ $ database ->deleteCollection ($ collectionId );
6340+ }
60236341}
0 commit comments