5353use OCP \IDBConnection ;
5454use OCP \IGroupManager ;
5555use OCP \IUserManager ;
56+ use OC \Search \Filter \DateTimeFilter ;
5657use PDO ;
5758use Sabre \CardDAV \Backend \BackendInterface ;
5859use Sabre \CardDAV \Backend \SyncSupport ;
@@ -1109,7 +1110,15 @@ public function searchPrincipalUri(string $principalUri,
11091110 * @param string $pattern
11101111 * @param array $searchProperties
11111112 * @param array $options
1112- * @psalm-param array{types?: bool, escape_like_param?: bool, limit?: int, offset?: int, wildcard?: bool} $options
1113+ * @psalm-param array{
1114+ * types?: bool,
1115+ * escape_like_param?: bool,
1116+ * limit?: int,
1117+ * offset?: int,
1118+ * wildcard?: bool,
1119+ * since?: DateTimeFilter|null,
1120+ * until?: DateTimeFilter|null,
1121+ * } $options
11131122 * @return array
11141123 */
11151124 private function searchByAddressBookIds (array $ addressBookIds ,
@@ -1130,32 +1139,31 @@ private function searchByAddressBookIds(array $addressBookIds,
11301139 return [];
11311140 }
11321141
1133- $ propertyOr = $ query2 ->expr ()->orX ();
1134- foreach ($ searchProperties as $ property ) {
1135- if ($ escapePattern ) {
1142+ if ($ escapePattern ) {
1143+ $ searchProperties = array_filter ($ searchProperties , function ($ property ) use ($ pattern ) {
11361144 if ($ property === 'EMAIL ' && str_contains ($ pattern , ' ' )) {
11371145 // There can be no spaces in emails
1138- continue ;
1146+ return false ;
11391147 }
11401148
11411149 if ($ property === 'CLOUD ' && preg_match ('/[^a-zA-Z0-9 :_.@\/\- \']/ ' , $ pattern ) === 1 ) {
11421150 // There can be no chars in cloud ids which are not valid for user ids plus :/
11431151 // worst case: CA61590A-BBBC-423E-84AF-E6DF01455A53@https://my.nxt/srv/
1144- continue ;
1152+ return false ;
11451153 }
1146- }
11471154
1148- $ propertyOr ->add ($ query2 ->expr ()->eq ('cp.name ' , $ query2 ->createNamedParameter ($ property )));
1155+ return true ;
1156+ });
11491157 }
11501158
1151- if ($ propertyOr -> count () === 0 ) {
1159+ if (empty ( $ searchProperties ) ) {
11521160 return [];
11531161 }
11541162
11551163 $ query2 ->selectDistinct ('cp.cardid ' )
11561164 ->from ($ this ->dbCardsPropertiesTable , 'cp ' )
11571165 ->andWhere ($ addressBookOr )
1158- ->andWhere ($ propertyOr );
1166+ ->andWhere ($ query2 -> expr ()-> in ( ' cp.name ' , $ query2 -> createNamedParameter ( $ searchProperties , IQueryBuilder:: PARAM_STR_ARRAY )) );
11591167
11601168 // No need for like when the pattern is empty
11611169 if ('' !== $ pattern ) {
@@ -1167,14 +1175,36 @@ private function searchByAddressBookIds(array $addressBookIds,
11671175 $ query2 ->andWhere ($ query2 ->expr ()->ilike ('cp.value ' , $ query2 ->createNamedParameter ('% ' . $ this ->db ->escapeLikeParameter ($ pattern ) . '% ' )));
11681176 }
11691177 }
1170-
11711178 if (isset ($ options ['limit ' ])) {
11721179 $ query2 ->setMaxResults ($ options ['limit ' ]);
11731180 }
11741181 if (isset ($ options ['offset ' ])) {
11751182 $ query2 ->setFirstResult ($ options ['offset ' ]);
11761183 }
11771184
1185+ if (isset ($ options ['since ' ]) || isset ($ options ['until ' ])) {
1186+ $ query2 ->join ('cp ' , $ this ->dbCardsPropertiesTable , 'cp_bday ' , 'cp.cardid = cp_bday.cardid ' );
1187+ $ query2 ->andWhere ($ query2 ->expr ()->eq ('cp_bday.name ' , $ query2 ->createNamedParameter ('BDAY ' )));
1188+ /**
1189+ * FIXME Find a way to match only 4 last digits
1190+ * BDAY can be --1018 without year or 20001019 with it
1191+ * $bDayOr = $query2->expr()->orX();
1192+ * if ($options['since'] instanceof DateTimeFilter) {
1193+ * $bDayOr->add(
1194+ * $query2->expr()->gte('SUBSTR(cp_bday.value, -4)',
1195+ * $query2->createNamedParameter($options['since']->get()->format('md')))
1196+ * );
1197+ * }
1198+ * if ($options['until'] instanceof DateTimeFilter) {
1199+ * $bDayOr->add(
1200+ * $query2->expr()->lte('SUBSTR(cp_bday.value, -4)',
1201+ * $query2->createNamedParameter($options['until']->get()->format('md')))
1202+ * );
1203+ * }
1204+ * $query2->andWhere($bDayOr);
1205+ */
1206+ }
1207+
11781208 $ result = $ query2 ->execute ();
11791209 $ matches = $ result ->fetchAll ();
11801210 $ result ->closeCursor ();
@@ -1410,7 +1440,7 @@ public function pruneOutdatedSyncTokens(int $keep = 10_000): int {
14101440 $ maxId = (int ) $ result ->fetchOne ();
14111441 $ result ->closeCursor ();
14121442 if (!$ maxId || $ maxId < $ keep ) {
1413- return 0 ;
1443+ return 0 ;
14141444 }
14151445
14161446 $ query = $ this ->db ->getQueryBuilder ();
0 commit comments