@@ -1695,6 +1695,86 @@ public function testOperatorArraySizeLimit(): void
16951695 $ database ->deleteCollection ($ collectionId );
16961696 }
16971697
1698+ /**
1699+ * An invalid array filter condition is rejected the same way on every adapter, because the
1700+ * operator validator checks it before any adapter runs.
1701+ */
1702+ public function testOperatorArrayFilterRejectsUnknownCondition (): void
1703+ {
1704+ $ database = static ::getDatabase ();
1705+
1706+ if (!$ database ->getAdapter ()->getSupportForOperators ()) {
1707+ $ this ->expectNotToPerformAssertions ();
1708+ return ;
1709+ }
1710+
1711+ $ collectionId = 'operator_filter_unknown_cond ' ;
1712+ $ database ->createCollection ($ collectionId );
1713+ $ database ->createAttribute ($ collectionId , 'tags ' , Database::VAR_STRING , 50 , false , null , true , true );
1714+
1715+ $ database ->createDocument ($ collectionId , new Document ([
1716+ '$id ' => 'doc ' ,
1717+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
1718+ 'tags ' => ['a ' , 'b ' , 'c ' ],
1719+ ]));
1720+
1721+ try {
1722+ $ database ->updateDocument ($ collectionId , 'doc ' , new Document ([
1723+ 'tags ' => Operator::arrayFilter ('bogusCondition ' , 'x ' ),
1724+ ]));
1725+ $ this ->fail ('Expected an exception for an invalid array filter condition ' );
1726+ } catch (DatabaseException $ e ) {
1727+ $ this ->assertStringContainsString ('filter condition ' , $ e ->getMessage ());
1728+ }
1729+
1730+ $ database ->deleteCollection ($ collectionId );
1731+ }
1732+
1733+ /**
1734+ * Every filter condition the validator accepts must actually work the same on all adapters.
1735+ * Each condition is applied to [1,2,3,4,5] and must keep exactly the matching elements —
1736+ * an adapter that doesn't handle a condition would keep the whole array instead.
1737+ */
1738+ public function testOperatorArrayFilterAllConditions (): void
1739+ {
1740+ $ database = static ::getDatabase ();
1741+
1742+ if (!$ database ->getAdapter ()->getSupportForOperators ()) {
1743+ $ this ->expectNotToPerformAssertions ();
1744+ return ;
1745+ }
1746+
1747+ $ collectionId = 'operator_filter_all_conditions ' ;
1748+ $ database ->createCollection ($ collectionId );
1749+ $ database ->createAttribute ($ collectionId , 'numbers ' , Database::VAR_INTEGER , 0 , false , null , true , true );
1750+ $ database ->createDocument ($ collectionId , new Document ([
1751+ '$id ' => 'doc ' ,
1752+ '$permissions ' => [Permission::read (Role::any ()), Permission::update (Role::any ())],
1753+ 'numbers ' => [1 , 2 , 3 , 4 , 5 ],
1754+ ]));
1755+
1756+ $ cases = [
1757+ ['equal ' , 3 , [3 ]],
1758+ ['notEqual ' , 3 , [1 , 2 , 4 , 5 ]],
1759+ ['greaterThan ' , 3 , [4 , 5 ]],
1760+ ['greaterThanEqual ' , 3 , [3 , 4 , 5 ]],
1761+ ['lessThan ' , 3 , [1 , 2 ]],
1762+ ['lessThanEqual ' , 3 , [1 , 2 , 3 ]],
1763+ ['isNotNull ' , null , [1 , 2 , 3 , 4 , 5 ]],
1764+ ['isNull ' , null , []],
1765+ ];
1766+
1767+ foreach ($ cases as [$ condition , $ compare , $ expected ]) {
1768+ $ database ->updateDocument ($ collectionId , 'doc ' , new Document (['numbers ' => [1 , 2 , 3 , 4 , 5 ]])); // reset
1769+ $ updated = $ database ->updateDocument ($ collectionId , 'doc ' , new Document ([
1770+ 'numbers ' => Operator::arrayFilter ($ condition , $ compare ),
1771+ ]));
1772+ $ this ->assertEquals ($ expected , \array_values ($ updated ->getAttribute ('numbers ' )), "arrayFilter(' {$ condition }') gave the wrong result " );
1773+ }
1774+
1775+ $ database ->deleteCollection ($ collectionId );
1776+ }
1777+
16981778 public function testOperatorStringConcatComprehensive (): void
16991779 {
17001780 $ database = static ::getDatabase ();
0 commit comments