AbstractPrincipalBackendTest.php 19 KB

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