AbstractPrincipalBackendTest.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2018, Georg Ehrke
  4. *
  5. * @author Georg Ehrke <oc.list@georgehrke.com>
  6. *
  7. * @license AGPL-3.0
  8. *
  9. * This code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License, version 3,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU Affero General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License, version 3,
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. namespace OCA\DAV\Tests\unit\CalDAV\ResourceBooking;
  23. use OCA\DAV\CalDAV\Proxy\Proxy;
  24. use OCA\DAV\CalDAV\Proxy\ProxyMapper;
  25. use OCP\DB\QueryBuilder\IQueryBuilder;
  26. use OCP\IGroupManager;
  27. use OCP\ILogger;
  28. use OCP\IUser;
  29. use OCP\IUserSession;
  30. use Sabre\DAV\PropPatch;
  31. use Test\TestCase;
  32. abstract class AbstractPrincipalBackendTest extends TestCase {
  33. /** @var \OCA\DAV\CalDAV\ResourceBooking\ResourcePrincipalBackend|\OCA\DAV\CalDAV\ResourceBooking\RoomPrincipalBackend */
  34. protected $principalBackend;
  35. /** @var IUserSession|\PHPUnit_Framework_MockObject_MockObject */
  36. protected $userSession;
  37. /** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */
  38. protected $groupManager;
  39. /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
  40. protected $logger;
  41. /** @var ProxyMapper|\PHPUnit_Framework_MockObject_MockObject */
  42. protected $proxyMapper;
  43. /** @var string */
  44. protected $mainDbTable;
  45. /** @var string */
  46. protected $metadataDbTable;
  47. /** @var string */
  48. protected $foreignKey;
  49. /** @var string */
  50. protected $principalPrefix;
  51. /** @var string */
  52. protected $expectedCUType;
  53. protected function setUp(): void {
  54. parent::setUp();
  55. $this->userSession = $this->createMock(IUserSession::class);
  56. $this->groupManager = $this->createMock(IGroupManager::class);
  57. $this->logger = $this->createMock(ILogger::class);
  58. $this->proxyMapper = $this->createMock(ProxyMapper::class);
  59. }
  60. protected function tearDown(): void {
  61. $query = self::$realDatabase->getQueryBuilder();
  62. $query->delete('calendar_resources')->execute();
  63. $query->delete('calendar_resources_md')->execute();
  64. $query->delete('calendar_rooms')->execute();
  65. $query->delete('calendar_rooms_md')->execute();
  66. }
  67. public function testGetPrincipalsByPrefix() {
  68. $actual = $this->principalBackend->getPrincipalsByPrefix($this->principalPrefix);
  69. $this->assertEquals([
  70. [
  71. 'uri' => $this->principalPrefix . '/backend1-res1',
  72. '{DAV:}displayname' => 'Beamer1',
  73. '{http://sabredav.org/ns}email-address' => 'res1@foo.bar',
  74. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  75. ],
  76. [
  77. 'uri' => $this->principalPrefix . '/backend1-res2',
  78. '{DAV:}displayname' => 'TV1',
  79. '{http://sabredav.org/ns}email-address' => 'res2@foo.bar',
  80. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  81. ],
  82. [
  83. 'uri' => $this->principalPrefix . '/backend2-res3',
  84. '{DAV:}displayname' => 'Beamer2',
  85. '{http://sabredav.org/ns}email-address' => 'res3@foo.bar',
  86. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  87. '{http://nextcloud.com/ns}foo' => 'value1',
  88. '{http://nextcloud.com/ns}meta2' => 'value2',
  89. ],
  90. [
  91. 'uri' => $this->principalPrefix . '/backend2-res4',
  92. '{DAV:}displayname' => 'TV2',
  93. '{http://sabredav.org/ns}email-address' => 'res4@foo.bar',
  94. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  95. '{http://nextcloud.com/ns}meta1' => 'value1',
  96. '{http://nextcloud.com/ns}meta3' => 'value3-old',
  97. ],
  98. [
  99. 'uri' => $this->principalPrefix . '/backend3-res5',
  100. '{DAV:}displayname' => 'Beamer3',
  101. '{http://sabredav.org/ns}email-address' => 'res5@foo.bar',
  102. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  103. ],
  104. [
  105. 'uri' => $this->principalPrefix . '/backend3-res6',
  106. '{DAV:}displayname' => 'Pointer',
  107. '{http://sabredav.org/ns}email-address' => 'res6@foo.bar',
  108. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  109. '{http://nextcloud.com/ns}meta99' => 'value99'
  110. ]
  111. ], $actual);
  112. }
  113. public function testGetNoPrincipalsByPrefixForWrongPrincipalPrefix() {
  114. $actual = $this->principalBackend->getPrincipalsByPrefix('principals/users');
  115. $this->assertEquals([], $actual);
  116. }
  117. public function testGetPrincipalByPath() {
  118. $actual = $this->principalBackend->getPrincipalByPath($this->principalPrefix . '/backend2-res3');
  119. $this->assertEquals([
  120. 'uri' => $this->principalPrefix . '/backend2-res3',
  121. '{DAV:}displayname' => 'Beamer2',
  122. '{http://sabredav.org/ns}email-address' => 'res3@foo.bar',
  123. '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => $this->expectedCUType,
  124. '{http://nextcloud.com/ns}foo' => 'value1',
  125. '{http://nextcloud.com/ns}meta2' => 'value2',
  126. ], $actual);
  127. }
  128. public function testGetPrincipalByPathNotFound() {
  129. $actual = $this->principalBackend->getPrincipalByPath($this->principalPrefix . '/db-123');
  130. $this->assertEquals(null, $actual);
  131. }
  132. public function testGetPrincipalByPathWrongPrefix() {
  133. $actual = $this->principalBackend->getPrincipalByPath('principals/users/foo-bar');
  134. $this->assertEquals(null, $actual);
  135. }
  136. public function testGetGroupMemberSet() {
  137. $actual = $this->principalBackend->getGroupMemberSet($this->principalPrefix . '/backend1-res1');
  138. $this->assertEquals([], $actual);
  139. }
  140. public function testGetGroupMemberSetProxyRead() {
  141. $proxy1 = new Proxy();
  142. $proxy1->setProxyId('proxyId1');
  143. $proxy1->setPermissions(1);
  144. $proxy2 = new Proxy();
  145. $proxy2->setProxyId('proxyId2');
  146. $proxy2->setPermissions(3);
  147. $proxy3 = new Proxy();
  148. $proxy3->setProxyId('proxyId3');
  149. $proxy3->setPermissions(3);
  150. $this->proxyMapper->expects($this->once())
  151. ->method('getProxiesOf')
  152. ->with($this->principalPrefix . '/backend1-res1')
  153. ->willReturn([$proxy1, $proxy2, $proxy3]);
  154. $actual = $this->principalBackend->getGroupMemberSet($this->principalPrefix . '/backend1-res1/calendar-proxy-read');
  155. $this->assertEquals(['proxyId1'], $actual);
  156. }
  157. public function testGetGroupMemberSetProxyWrite() {
  158. $proxy1 = new Proxy();
  159. $proxy1->setProxyId('proxyId1');
  160. $proxy1->setPermissions(1);
  161. $proxy2 = new Proxy();
  162. $proxy2->setProxyId('proxyId2');
  163. $proxy2->setPermissions(3);
  164. $proxy3 = new Proxy();
  165. $proxy3->setProxyId('proxyId3');
  166. $proxy3->setPermissions(3);
  167. $this->proxyMapper->expects($this->once())
  168. ->method('getProxiesOf')
  169. ->with($this->principalPrefix . '/backend1-res1')
  170. ->willReturn([$proxy1, $proxy2, $proxy3]);
  171. $actual = $this->principalBackend->getGroupMemberSet($this->principalPrefix . '/backend1-res1/calendar-proxy-write');
  172. $this->assertEquals(['proxyId2', 'proxyId3'], $actual);
  173. }
  174. public function testGetGroupMembership() {
  175. $proxy1 = new Proxy();
  176. $proxy1->setOwnerId('proxyId1');
  177. $proxy1->setPermissions(1);
  178. $proxy2 = new Proxy();
  179. $proxy2->setOwnerId('proxyId2');
  180. $proxy2->setPermissions(3);
  181. $this->proxyMapper->expects($this->once())
  182. ->method('getProxiesFor')
  183. ->with($this->principalPrefix . '/backend1-res1')
  184. ->willReturn([$proxy1, $proxy2]);
  185. $actual = $this->principalBackend->getGroupMembership($this->principalPrefix . '/backend1-res1');
  186. $this->assertEquals(['proxyId1/calendar-proxy-read', 'proxyId2/calendar-proxy-write'], $actual);
  187. }
  188. public function testSetGroupMemberSet() {
  189. $this->proxyMapper->expects($this->at(0))
  190. ->method('getProxiesOf')
  191. ->with($this->principalPrefix . '/backend1-res1')
  192. ->willReturn([]);
  193. $this->proxyMapper->expects($this->at(1))
  194. ->method('insert')
  195. ->with($this->callback(function($proxy) {
  196. /** @var Proxy $proxy */
  197. if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
  198. return false;
  199. }
  200. if ($proxy->getProxyId() !== $this->principalPrefix . '/backend1-res2') {
  201. return false;
  202. }
  203. if ($proxy->getPermissions() !== 3) {
  204. return false;
  205. }
  206. return true;
  207. }));
  208. $this->proxyMapper->expects($this->at(2))
  209. ->method('insert')
  210. ->with($this->callback(function($proxy) {
  211. /** @var Proxy $proxy */
  212. if ($proxy->getOwnerId() !== $this->principalPrefix . '/backend1-res1') {
  213. return false;
  214. }
  215. if ($proxy->getProxyId() !== $this->principalPrefix . '/backend2-res3') {
  216. return false;
  217. }
  218. if ($proxy->getPermissions() !== 3) {
  219. return false;
  220. }
  221. return true;
  222. }));
  223. $this->principalBackend->setGroupMemberSet($this->principalPrefix . '/backend1-res1/calendar-proxy-write', [$this->principalPrefix . '/backend1-res2', $this->principalPrefix . '/backend2-res3']);
  224. }
  225. public function testUpdatePrincipal() {
  226. $propPatch = $this->createMock(PropPatch::class);
  227. $actual = $this->principalBackend->updatePrincipal($this->principalPrefix . '/foo-bar', $propPatch);
  228. $this->assertEquals(0, $actual);
  229. }
  230. /**
  231. * @dataProvider dataSearchPrincipals
  232. */
  233. public function testSearchPrincipals($expected, $test) {
  234. $user = $this->createMock(IUser::class);
  235. $this->userSession->expects($this->once())
  236. ->method('getUser')
  237. ->with()
  238. ->will($this->returnValue($user));
  239. $this->groupManager->expects($this->once())
  240. ->method('getUserGroupIds')
  241. ->with($user)
  242. ->will($this->returnValue(['group1', 'group2']));
  243. $actual = $this->principalBackend->searchPrincipals($this->principalPrefix, [
  244. '{http://sabredav.org/ns}email-address' => 'foo',
  245. '{DAV:}displayname' => 'Beamer',
  246. ], $test);
  247. $this->assertEquals(
  248. str_replace('%prefix%', $this->principalPrefix, $expected),
  249. $actual);
  250. }
  251. public function dataSearchPrincipals() {
  252. // data providers are called before we subclass
  253. // this class, $this->principalPrefix is null
  254. // at that point, so we need this hack
  255. return [
  256. [[
  257. '%prefix%/backend1-res1',
  258. '%prefix%/backend2-res3',
  259. ], 'allof'],
  260. [[
  261. '%prefix%/backend1-res1',
  262. '%prefix%/backend1-res2',
  263. '%prefix%/backend2-res3',
  264. '%prefix%/backend2-res4',
  265. '%prefix%/backend3-res6',
  266. ], 'anyof'],
  267. ];
  268. }
  269. public function testSearchPrincipalsByMetadataKey() {
  270. $user = $this->createMock(IUser::class);
  271. $this->userSession->expects($this->once())
  272. ->method('getUser')
  273. ->with()
  274. ->will($this->returnValue($user));
  275. $this->groupManager->expects($this->once())
  276. ->method('getUserGroupIds')
  277. ->with($user)
  278. ->will($this->returnValue(['group1', 'group2']));
  279. $actual = $this->principalBackend->searchPrincipals($this->principalPrefix, [
  280. '{http://nextcloud.com/ns}meta3' => 'value',
  281. ]);
  282. $this->assertEquals([
  283. $this->principalPrefix . '/backend2-res4',
  284. ], $actual);
  285. }
  286. public function testSearchPrincipalsByCalendarUserAddressSet() {
  287. $user = $this->createMock(IUser::class);
  288. $this->userSession->method('getUser')
  289. ->with()
  290. ->will($this->returnValue($user));
  291. $this->groupManager->method('getUserGroupIds')
  292. ->with($user)
  293. ->will($this->returnValue(['group1', 'group2']));
  294. $actual = $this->principalBackend->searchPrincipals($this->principalPrefix, [
  295. '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set' => 'res2@foo.bar',
  296. ]);
  297. $this->assertEquals(
  298. str_replace('%prefix%', $this->principalPrefix, [
  299. '%prefix%/backend1-res2',
  300. ]),
  301. $actual);
  302. }
  303. public function testSearchPrincipalsEmptySearchProperties() {
  304. $this->userSession->expects($this->never())
  305. ->method('getUser');
  306. $this->groupManager->expects($this->never())
  307. ->method('getUserGroupIds');
  308. $this->principalBackend->searchPrincipals($this->principalPrefix, []);
  309. }
  310. public function testSearchPrincipalsWrongPrincipalPrefix() {
  311. $this->userSession->expects($this->never())
  312. ->method('getUser');
  313. $this->groupManager->expects($this->never())
  314. ->method('getUserGroupIds');
  315. $this->principalBackend->searchPrincipals('principals/users', [
  316. '{http://sabredav.org/ns}email-address' => 'foo'
  317. ]);
  318. }
  319. public function testFindByUriByEmail() {
  320. $user = $this->createMock(IUser::class);
  321. $this->userSession->expects($this->once())
  322. ->method('getUser')
  323. ->with()
  324. ->will($this->returnValue($user));
  325. $this->groupManager->expects($this->once())
  326. ->method('getUserGroupIds')
  327. ->with($user)
  328. ->will($this->returnValue(['group1', 'group2']));
  329. $actual = $this->principalBackend->findByUri('mailto:res1@foo.bar', $this->principalPrefix);
  330. $this->assertEquals($this->principalPrefix . '/backend1-res1', $actual);
  331. }
  332. public function testFindByUriByEmailForbiddenResource() {
  333. $user = $this->createMock(IUser::class);
  334. $this->userSession->expects($this->once())
  335. ->method('getUser')
  336. ->with()
  337. ->will($this->returnValue($user));
  338. $this->groupManager->expects($this->once())
  339. ->method('getUserGroupIds')
  340. ->with($user)
  341. ->will($this->returnValue(['group1', 'group2']));
  342. $actual = $this->principalBackend->findByUri('mailto:res5@foo.bar', $this->principalPrefix);
  343. $this->assertEquals(null, $actual);
  344. }
  345. public function testFindByUriByEmailNotFound() {
  346. $user = $this->createMock(IUser::class);
  347. $this->userSession->expects($this->once())
  348. ->method('getUser')
  349. ->with()
  350. ->will($this->returnValue($user));
  351. $this->groupManager->expects($this->once())
  352. ->method('getUserGroupIds')
  353. ->with($user)
  354. ->will($this->returnValue(['group1', 'group2']));
  355. $actual = $this->principalBackend->findByUri('mailto:res99@foo.bar', $this->principalPrefix);
  356. $this->assertEquals(null, $actual);
  357. }
  358. public function testFindByUriByPrincipal() {
  359. $user = $this->createMock(IUser::class);
  360. $this->userSession->expects($this->once())
  361. ->method('getUser')
  362. ->with()
  363. ->will($this->returnValue($user));
  364. $this->groupManager->expects($this->once())
  365. ->method('getUserGroupIds')
  366. ->with($user)
  367. ->will($this->returnValue(['group1', 'group2']));
  368. $actual = $this->principalBackend->findByUri('mailto:res6@foo.bar', $this->principalPrefix);
  369. $this->assertEquals($this->principalPrefix . '/backend3-res6', $actual);
  370. }
  371. public function testFindByUriByPrincipalForbiddenResource() {
  372. $user = $this->createMock(IUser::class);
  373. $this->userSession->expects($this->once())
  374. ->method('getUser')
  375. ->with()
  376. ->will($this->returnValue($user));
  377. $this->groupManager->expects($this->once())
  378. ->method('getUserGroupIds')
  379. ->with($user)
  380. ->will($this->returnValue(['group1', 'group2']));
  381. $actual = $this->principalBackend->findByUri('principal:' . $this->principalPrefix . '/backend3-res5', $this->principalPrefix);
  382. $this->assertEquals(null, $actual);
  383. }
  384. public function testFindByUriByPrincipalNotFound() {
  385. $user = $this->createMock(IUser::class);
  386. $this->userSession->expects($this->once())
  387. ->method('getUser')
  388. ->with()
  389. ->will($this->returnValue($user));
  390. $this->groupManager->expects($this->once())
  391. ->method('getUserGroupIds')
  392. ->with($user)
  393. ->will($this->returnValue(['group1', 'group2']));
  394. $actual = $this->principalBackend->findByUri('principal:' . $this->principalPrefix . '/db-123', $this->principalPrefix);
  395. $this->assertEquals(null, $actual);
  396. }
  397. public function testFindByUriByUnknownUri() {
  398. $user = $this->createMock(IUser::class);
  399. $this->userSession->expects($this->once())
  400. ->method('getUser')
  401. ->with()
  402. ->will($this->returnValue($user));
  403. $this->groupManager->expects($this->once())
  404. ->method('getUserGroupIds')
  405. ->with($user)
  406. ->will($this->returnValue(['group1', 'group2']));
  407. $actual = $this->principalBackend->findByUri('foobar:blub', $this->principalPrefix);
  408. $this->assertEquals(null, $actual);
  409. }
  410. protected function createTestDatasetInDb() {
  411. $query = self::$realDatabase->getQueryBuilder();
  412. $query->insert($this->mainDbTable)
  413. ->values([
  414. 'backend_id' => $query->createNamedParameter('backend1'),
  415. 'resource_id' => $query->createNamedParameter('res1'),
  416. 'email' => $query->createNamedParameter('res1@foo.bar'),
  417. 'displayname' => $query->createNamedParameter('Beamer1'),
  418. 'group_restrictions' => $query->createNamedParameter('[]'),
  419. ])
  420. ->execute();
  421. $query->insert($this->mainDbTable)
  422. ->values([
  423. 'backend_id' => $query->createNamedParameter('backend1'),
  424. 'resource_id' => $query->createNamedParameter('res2'),
  425. 'email' => $query->createNamedParameter('res2@foo.bar'),
  426. 'displayname' => $query->createNamedParameter('TV1'),
  427. 'group_restrictions' => $query->createNamedParameter('[]'),
  428. ])
  429. ->execute();
  430. $query->insert($this->mainDbTable)
  431. ->values([
  432. 'backend_id' => $query->createNamedParameter('backend2'),
  433. 'resource_id' => $query->createNamedParameter('res3'),
  434. 'email' => $query->createNamedParameter('res3@foo.bar'),
  435. 'displayname' => $query->createNamedParameter('Beamer2'),
  436. 'group_restrictions' => $query->createNamedParameter('[]'),
  437. ])
  438. ->execute();
  439. $id3 = $query->getLastInsertId();
  440. $query->insert($this->mainDbTable)
  441. ->values([
  442. 'backend_id' => $query->createNamedParameter('backend2'),
  443. 'resource_id' => $query->createNamedParameter('res4'),
  444. 'email' => $query->createNamedParameter('res4@foo.bar'),
  445. 'displayname' => $query->createNamedParameter('TV2'),
  446. 'group_restrictions' => $query->createNamedParameter('[]'),
  447. ])
  448. ->execute();
  449. $id4 = $query->getLastInsertId();
  450. $query->insert($this->mainDbTable)
  451. ->values([
  452. 'backend_id' => $query->createNamedParameter('backend3'),
  453. 'resource_id' => $query->createNamedParameter('res5'),
  454. 'email' => $query->createNamedParameter('res5@foo.bar'),
  455. 'displayname' => $query->createNamedParameter('Beamer3'),
  456. 'group_restrictions' => $query->createNamedParameter('["foo", "bar"]'),
  457. ])
  458. ->execute();
  459. $query->insert($this->mainDbTable)
  460. ->values([
  461. 'backend_id' => $query->createNamedParameter('backend3'),
  462. 'resource_id' => $query->createNamedParameter('res6'),
  463. 'email' => $query->createNamedParameter('res6@foo.bar'),
  464. 'displayname' => $query->createNamedParameter('Pointer'),
  465. 'group_restrictions' => $query->createNamedParameter('["group1", "bar"]'),
  466. ])
  467. ->execute();
  468. $id6 = $query->getLastInsertId();
  469. $query->insert($this->metadataDbTable)
  470. ->values([
  471. $this->foreignKey => $query->createNamedParameter($id3),
  472. 'key' => $query->createNamedParameter('{http://nextcloud.com/ns}foo'),
  473. 'value' => $query->createNamedParameter('value1')
  474. ])
  475. ->execute();
  476. $query->insert($this->metadataDbTable)
  477. ->values([
  478. $this->foreignKey => $query->createNamedParameter($id3),
  479. 'key' => $query->createNamedParameter('{http://nextcloud.com/ns}meta2'),
  480. 'value' => $query->createNamedParameter('value2')
  481. ])
  482. ->execute();
  483. $query->insert($this->metadataDbTable)
  484. ->values([
  485. $this->foreignKey => $query->createNamedParameter($id4),
  486. 'key' => $query->createNamedParameter('{http://nextcloud.com/ns}meta1'),
  487. 'value' => $query->createNamedParameter('value1')
  488. ])
  489. ->execute();
  490. $query->insert($this->metadataDbTable)
  491. ->values([
  492. $this->foreignKey => $query->createNamedParameter($id4),
  493. 'key' => $query->createNamedParameter('{http://nextcloud.com/ns}meta3'),
  494. 'value' => $query->createNamedParameter('value3-old')
  495. ])
  496. ->execute();
  497. $query->insert($this->metadataDbTable)
  498. ->values([
  499. $this->foreignKey => $query->createNamedParameter($id6),
  500. 'key' => $query->createNamedParameter('{http://nextcloud.com/ns}meta99'),
  501. 'value' => $query->createNamedParameter('value99')
  502. ])
  503. ->execute();
  504. }
  505. }