TYPO3 CMS  TYPO3_7-6
Typo3DatabaseBackendTest.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
20 
25 {
26 
30  public function getReturnsPreviouslySetEntry()
31  {
32  $frontendProphecy = $this->prophesize(FrontendInterface::class);
33  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
34 
35  $subject = new Typo3DatabaseBackend('Testing');
36  $subject->setCache($frontendProphecy->reveal());
37 
38  $subject->set('myIdentifier', 'myData');
39  $this->assertSame('myData', $subject->get('myIdentifier'));
40  }
41 
46  {
47  $frontendProphecy = $this->prophesize(FrontendInterface::class);
48  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
49 
50  $subject = new Typo3DatabaseBackend('Testing');
51  $subject->setCache($frontendProphecy->reveal());
52 
53  $subject->set('myIdentifier', 'myData');
54  $subject->set('myIdentifier', 'myNewData');
55  $this->assertSame('myNewData', $subject->get('myIdentifier'));
56  }
57 
62  {
63  $frontendProphecy = $this->prophesize(FrontendInterface::class);
64  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
65 
66  $subject = new Typo3DatabaseBackend('Testing');
67  $subject->setCache($frontendProphecy->reveal());
68 
69  $subject->set('myIdentifier', 'myData', ['aTag', 'anotherTag']);
70 
71  $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="myIdentifier"');
72  $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="myIdentifier" AND tag="aTag"');
73  $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="myIdentifier" AND tag="anotherTag"');
74  }
75 
79  public function setStoresCompressedContent()
80  {
81  $frontendProphecy = $this->prophesize(FrontendInterface::class);
82  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
83 
84  // Have backend with compression enabled
85  $subject = new Typo3DatabaseBackend('Testing', ['compression' => true]);
86  $subject->setCache($frontendProphecy->reveal());
87 
88  $subject->set('myIdentifier', 'myCachedContent');
89 
90  $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
91  'content',
92  'cf_cache_pages',
93  'identifier="myIdentifier"'
94  );
95 
96  // Content comes back uncompressed
97  $this->assertSame('myCachedContent', gzuncompress($row['content']));
98  }
99 
104  {
105  $frontendProphecy = $this->prophesize(FrontendInterface::class);
106  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
107 
108  $subject = new Typo3DatabaseBackend('Testing');
109  $subject->setCache($frontendProphecy->reveal());
110 
111  $this->assertFalse($subject->get('myIdentifier'));
112  }
113 
118  {
119  $frontendProphecy = $this->prophesize(FrontendInterface::class);
120  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
121 
122  // Push an expired row into db
123  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
124  'cf_cache_pages',
125  [
126  'identifier' => 'myIdentifier',
127  'expires' => $GLOBALS['EXEC_TIME'] - 60,
128  'content' => 'myCachedContent',
129  ]
130  );
131 
132  $subject = new Typo3DatabaseBackend('Testing');
133  $subject->setCache($frontendProphecy->reveal());
134 
135  $this->assertFalse($subject->get('myIdentifier'));
136  }
137 
142  {
143  $frontendProphecy = $this->prophesize(FrontendInterface::class);
144  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
145 
146  // Push a row into db
147  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
148  'cf_cache_pages',
149  [
150  'identifier' => 'myIdentifier',
151  'expires' => $GLOBALS['EXEC_TIME'] + 60,
152  'content' => 'myCachedContent',
153  ]
154  );
155 
156  $subject = new Typo3DatabaseBackend('Testing');
157  $subject->setCache($frontendProphecy->reveal());
158 
159  $this->assertSame('myCachedContent', $subject->get('myIdentifier'));
160  }
161 
166  {
167  $frontendProphecy = $this->prophesize(FrontendInterface::class);
168  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
169 
170  // Push a compressed row into db
171  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
172  'cf_cache_pages',
173  [
174  'identifier' => 'myIdentifier',
175  'expires' => $GLOBALS['EXEC_TIME'] + 60,
176  'content' => gzcompress('myCachedContent'),
177  ]
178  );
179 
180  // Have backend with compression enabled
181  $subject = new Typo3DatabaseBackend('Testing', ['compression' => true]);
182  $subject->setCache($frontendProphecy->reveal());
183 
184  // Content comes back uncompressed
185  $this->assertSame('myCachedContent', $subject->get('myIdentifier'));
186  }
187 
192  {
193  $frontendProphecy = $this->prophesize(FrontendInterface::class);
194  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
195 
196  // Push a compressed row into db
197  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
198  'cf_cache_pages',
199  [
200  'identifier' => 'myIdentifier',
201  'expires' => $GLOBALS['EXEC_TIME'] + 60,
202  'content' => gzcompress(''),
203  ]
204  );
205 
206  // Have backend with compression enabled
207  $subject = new Typo3DatabaseBackend('Testing', ['compression' => true]);
208  $subject->setCache($frontendProphecy->reveal());
209 
210  // Content comes back uncompressed
211  $this->assertSame('', $subject->get('myIdentifier'));
212  }
213 
218  {
219  $frontendProphecy = $this->prophesize(FrontendInterface::class);
220  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
221 
222  $subject = new Typo3DatabaseBackend('Testing');
223  $subject->setCache($frontendProphecy->reveal());
224 
225  $this->assertFalse($subject->has('myIdentifier'));
226  }
227 
232  {
233  $frontendProphecy = $this->prophesize(FrontendInterface::class);
234  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
235 
236  // Push an expired row into db
237  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
238  'cf_cache_pages',
239  [
240  'identifier' => 'myIdentifier',
241  'expires' => $GLOBALS['EXEC_TIME'] - 60,
242  'content' => 'myCachedContent',
243  ]
244  );
245 
246  $subject = new Typo3DatabaseBackend('Testing');
247  $subject->setCache($frontendProphecy->reveal());
248 
249  $this->assertFalse($subject->has('myIdentifier'));
250  }
251 
256  {
257  $frontendProphecy = $this->prophesize(FrontendInterface::class);
258  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
259 
260  // Push a row into db
261  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
262  'cf_cache_pages',
263  [
264  'identifier' => 'myIdentifier',
265  'expires' => $GLOBALS['EXEC_TIME'] + 60,
266  'content' => 'myCachedContent',
267  ]
268  );
269 
270  $subject = new Typo3DatabaseBackend('Testing');
271  $subject->setCache($frontendProphecy->reveal());
272 
273  $this->assertTrue($subject->has('myIdentifier'));
274  }
275 
280  {
281  $frontendProphecy = $this->prophesize(FrontendInterface::class);
282  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
283 
284  $subject = new Typo3DatabaseBackend('Testing');
285  $subject->setCache($frontendProphecy->reveal());
286 
287  $this->assertFalse($subject->remove('myIdentifier'));
288  }
289 
294  {
295  $frontendProphecy = $this->prophesize(FrontendInterface::class);
296  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
297 
298  // Push a row into db
299  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
300  'cf_cache_pages',
301  [
302  'identifier' => 'myIdentifier',
303  'expires' => $GLOBALS['EXEC_TIME'] + 60,
304  'content' => 'myCachedContent',
305  ]
306  );
307  $subject = new Typo3DatabaseBackend('Testing');
308  $subject->setCache($frontendProphecy->reveal());
309  $this->assertTrue($subject->remove('myIdentifier'));
310  }
311 
316  {
317  $frontendProphecy = $this->prophesize(FrontendInterface::class);
318  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
319 
320  // Add one cache row to remove and another one that shouldn't be removed
321  $GLOBALS['TYPO3_DB']->INSERTmultipleRows(
322  'cf_cache_pages',
323  ['identifier', 'expires', 'content'],
324  [
325  ['myIdentifier', $GLOBALS['EXEC_TIME'] + 60, 'myCachedContent'],
326  ['otherIdentifier', $GLOBALS['EXEC_TIME'] + 60, 'otherCachedContent'],
327  ]
328  );
329 
330  $subject = new Typo3DatabaseBackend('Testing');
331  $subject->setCache($frontendProphecy->reveal());
332 
333  // Add a couple of tags
334  $GLOBALS['TYPO3_DB']->INSERTmultipleRows(
335  'cf_cache_pages',
336  ['identifier', 'tag'],
337  [
338  ['myIdentifier', 'aTag'],
339  ['myIdentifier', 'otherTag'],
340  ['otherIdentifier', 'aTag'],
341  ['otherIdentifier', 'otherTag'],
342  ]
343  );
344 
345  $subject->remove('myIdentifier');
346 
347  // cache row with removed identifier has been removed, other one exists
348  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="myIdentifier"'));
349  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="otherIdentifier"'));
350 
351  // tags of myIdentifier should have been removed, others exist
352  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="myIdentifier"'));
353  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="otherIdentifier"'));
354  }
355 
360  {
361  $frontendProphecy = $this->prophesize(FrontendInterface::class);
362  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
363 
364  $subject = new Typo3DatabaseBackend('Testing');
365  $subject->setCache($frontendProphecy->reveal());
366 
367  $subject->set('idA', 'dataA', ['tagA', 'tagB']);
368  $subject->set('idB', 'dataB', ['tagB', 'tagC']);
369 
370  $this->assertSame(['idA' => 'idA'], $subject->findIdentifiersByTag('tagA'));
371  $this->assertSame(['idA' => 'idA', 'idB' => 'idB'], $subject->findIdentifiersByTag('tagB'));
372  $this->assertSame(['idB' => 'idB'], $subject->findIdentifiersByTag('tagC'));
373  }
374 
379  {
380  $frontendProphecy = $this->prophesize(FrontendInterface::class);
381  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
382 
383  // Must be mocked here to test for "mysql" version implementation
384  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
385  ->setMethods(['isConnectionMysql'])
386  ->setConstructorArgs(['Testing'])
387  ->getMock();
388  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(true);
389  $subject->setCache($frontendProphecy->reveal());
390 
391  $subject->flushByTag('tagB');
392  }
393 
398  {
399  $frontendProphecy = $this->prophesize(FrontendInterface::class);
400  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
401 
402  // Must be mocked here to test for "mysql" version implementation
403  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
404  ->setMethods(['isConnectionMysql'])
405  ->setConstructorArgs(['Testing'])
406  ->getMock();
407  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(true);
408  $subject->setCache($frontendProphecy->reveal());
409 
410  $subject->set('idA', 'dataA', ['tagA', 'tagB']);
411  $subject->set('idB', 'dataB', ['tagB', 'tagC']);
412  $subject->set('idC', 'dataC', ['tagC', 'tagD']);
413  $subject->flushByTag('tagB');
414 
415  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idA"'));
416  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idB"'));
417  $this->assertSame(1, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idC"'));
418  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idA"'));
419  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idB"'));
420  $this->assertSame(2, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idC"'));
421  }
422 
427  {
428  $frontendProphecy = $this->prophesize(FrontendInterface::class);
429  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
430 
431  // Must be mocked here to test for "mysql" version implementation
432  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
433  ->setMethods(['isConnectionMysql'])
434  ->setConstructorArgs(['Testing'])
435  ->getMock();
436  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(false);
437  $subject->setCache($frontendProphecy->reveal());
438 
439  $subject->flushByTag('tagB');
440  }
441 
446  {
447  $frontendProphecy = $this->prophesize(FrontendInterface::class);
448  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
449 
450  // Must be mocked here to test for "mysql" version implementation
451  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
452  ->setMethods(['isConnectionMysql'])
453  ->setConstructorArgs(['Testing'])
454  ->getMock();
455  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(false);
456  $subject->setCache($frontendProphecy->reveal());
457 
458  $subject->set('idA', 'dataA', ['tagA', 'tagB']);
459  $subject->set('idB', 'dataB', ['tagB', 'tagC']);
460  $subject->set('idC', 'dataC', ['tagC', 'tagD']);
461  $subject->flushByTag('tagB');
462 
463  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idA"'));
464  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idB"'));
465  $this->assertSame(1, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idC"'));
466  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idA"'));
467  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idB"'));
468  $this->assertSame(2, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idC"'));
469  }
470 
475  {
476  $frontendProphecy = $this->prophesize(FrontendInterface::class);
477  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
478 
479  // Must be mocked here to test for "mysql" version implementation
480  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
481  ->setMethods(['isConnectionMysql'])
482  ->setConstructorArgs(['Testing'])
483  ->getMock();
484  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(true);
485  $subject->setCache($frontendProphecy->reveal());
486 
487  $subject->collectGarbage();
488  }
489 
494  {
495  $frontendProphecy = $this->prophesize(FrontendInterface::class);
496  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
497 
498  // Must be mocked here to test for "mysql" version implementation
499  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
500  ->setMethods(['isConnectionMysql'])
501  ->setConstructorArgs(['Testing'])
502  ->getMock();
503  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(true);
504  $subject->setCache($frontendProphecy->reveal());
505 
506  // idA should be expired after EXEC_TIME manipulation, idB should stay
507  $subject->set('idA', 'dataA', [], 60);
508  $subject->set('idB', 'dataB', [], 240);
509 
510  $GLOBALS['EXEC_TIME'] = $GLOBALS['EXEC_TIME'] + 120;
511 
512  $subject->collectGarbage();
513 
514  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idA"'));
515  $this->assertSame(1, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idB"'));
516  }
517 
522  {
523  $frontendProphecy = $this->prophesize(FrontendInterface::class);
524  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
525 
526  // Must be mocked here to test for "mysql" version implementation
527  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
528  ->setMethods(['isConnectionMysql'])
529  ->setConstructorArgs(['Testing'])
530  ->getMock();
531  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(true);
532  $subject->setCache($frontendProphecy->reveal());
533 
534  // tag rows tagA and tagB should be removed by garbage collector after EXEC_TIME manipulation
535  $subject->set('idA', 'dataA', ['tagA', 'tagB'], 60);
536  $subject->set('idB', 'dataB', ['tagB', 'tagC'], 240);
537 
538  $GLOBALS['EXEC_TIME'] = $GLOBALS['EXEC_TIME'] + 120;
539 
540  $subject->collectGarbage();
541 
542  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idA"'));
543  $this->assertSame(2, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idB"'));
544  }
545 
550  {
551  $frontendProphecy = $this->prophesize(FrontendInterface::class);
552  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
553 
554  // Must be mocked here to test for "mysql" version implementation
555  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
556  ->setMethods(['isConnectionMysql'])
557  ->setConstructorArgs(['Testing'])
558  ->getMock();
559  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(true);
560  $subject->setCache($frontendProphecy->reveal());
561 
562  // tag rows tagA and tagB should be removed by garbage collector after EXEC_TIME manipulation
563  $subject->set('idA', 'dataA', ['tagA', 'tagB'], 60);
564  $subject->set('idB', 'dataB', ['tagB', 'tagC'], 240);
565 
566  // Push two orphaned tag row into db - tags that have no related cache record anymore for whatever reason
567  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
568  'cf_cache_pages_tags',
569  [
570  'identifier' => 'idC',
571  'tag' => 'tagC'
572  ]
573  );
574  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
575  'cf_cache_pages_tags',
576  [
577  'identifier' => 'idC',
578  'tag' => 'tagD'
579  ]
580  );
581 
582  $GLOBALS['EXEC_TIME'] = $GLOBALS['EXEC_TIME'] + 120;
583 
584  $subject->collectGarbage();
585 
586  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idA"'));
587  $this->assertSame(2, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idB"'));
588  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idC"'));
589  }
590 
595  {
596  $frontendProphecy = $this->prophesize(FrontendInterface::class);
597  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
598 
599  // Must be mocked here to test for "mysql" version implementation
600  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
601  ->setMethods(['isConnectionMysql'])
602  ->setConstructorArgs(['Testing'])
603  ->getMock();
604  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(false);
605  $subject->setCache($frontendProphecy->reveal());
606 
607  $subject->collectGarbage();
608  }
609 
614  {
615  $frontendProphecy = $this->prophesize(FrontendInterface::class);
616  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
617 
618  // Must be mocked here to test for "mysql" version implementation
619  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
620  ->setMethods(['isConnectionMysql'])
621  ->setConstructorArgs(['Testing'])
622  ->getMock();
623  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(false);
624  $subject->setCache($frontendProphecy->reveal());
625 
626  // idA should be expired after EXEC_TIME manipulation, idB should stay
627  $subject->set('idA', 'dataA', [], 60);
628  $subject->set('idB', 'dataB', [], 240);
629 
630  $GLOBALS['EXEC_TIME'] = $GLOBALS['EXEC_TIME'] + 120;
631 
632  $subject->collectGarbage();
633 
634  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idA"'));
635  $this->assertSame(1, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages', 'identifier="idB"'));
636  }
637 
642  {
643  $frontendProphecy = $this->prophesize(FrontendInterface::class);
644  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
645 
646  // Must be mocked here to test for "mysql" version implementation
647  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
648  ->setMethods(['isConnectionMysql'])
649  ->setConstructorArgs(['Testing'])
650  ->getMock();
651  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(false);
652  $subject->setCache($frontendProphecy->reveal());
653 
654  // tag rows tagA and tagB should be removed by garbage collector after EXEC_TIME manipulation
655  $subject->set('idA', 'dataA', ['tagA', 'tagB'], 60);
656  $subject->set('idB', 'dataB', ['tagB', 'tagC'], 240);
657 
658  $GLOBALS['EXEC_TIME'] = $GLOBALS['EXEC_TIME'] + 120;
659 
660  $subject->collectGarbage();
661 
662  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idA"'));
663  $this->assertSame(2, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idB"'));
664  }
665 
670  {
671  $frontendProphecy = $this->prophesize(FrontendInterface::class);
672  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
673 
674  // Must be mocked here to test for "mysql" version implementation
675  $subject = $this->getMockBuilder(Typo3DatabaseBackend::class)
676  ->setMethods(['isConnectionMysql'])
677  ->setConstructorArgs(['Testing'])
678  ->getMock();
679  $subject->expects($this->once())->method('isConnectionMysql')->willReturn(false);
680  $subject->setCache($frontendProphecy->reveal());
681 
682  // tag rows tagA and tagB should be removed by garbage collector after EXEC_TIME manipulation
683  $subject->set('idA', 'dataA', ['tagA', 'tagB'], 60);
684  $subject->set('idB', 'dataB', ['tagB', 'tagC'], 240);
685 
686  // Push two orphaned tag row into db - tags that have no related cache record anymore for whatever reason
687  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
688  'cf_cache_pages_tags',
689  [
690  'identifier' => 'idC',
691  'tag' => 'tagC'
692  ]
693  );
694  $GLOBALS['TYPO3_DB']->exec_INSERTquery(
695  'cf_cache_pages_tags',
696  [
697  'identifier' => 'idC',
698  'tag' => 'tagD'
699  ]
700  );
701 
702  $GLOBALS['EXEC_TIME'] = $GLOBALS['EXEC_TIME'] + 120;
703 
704  $subject->collectGarbage();
705 
706  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idA"'));
707  $this->assertSame(2, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idB"'));
708  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags', 'identifier="idC"'));
709  }
710 
715  {
716  $frontendProphecy = $this->prophesize(FrontendInterface::class);
717  $frontendProphecy->getIdentifier()->willReturn('cache_pages');
718 
719  $subject = new Typo3DatabaseBackend('Testing');
720  $subject->setCache($frontendProphecy->reveal());
721 
722  $subject->set('idA', 'dataA', ['tagA', 'tagB']);
723 
724  $subject->flush();
725 
726  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages'));
727  $this->assertSame(0, $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('*', 'cf_cache_pages_tags'));
728  }
729 }
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']