2017-08-18 02:36:15 +00:00
|
|
|
<?php
|
2017-11-17 01:23:18 +00:00
|
|
|
/** @license MIT
|
|
|
|
* Copyright 2017 J. King, Dustin Wilson et al.
|
|
|
|
* See LICENSE and AUTHORS files for details */
|
|
|
|
|
2017-08-18 02:36:15 +00:00
|
|
|
declare(strict_types=1);
|
2018-11-23 15:01:17 +00:00
|
|
|
namespace JKingWeb\Arsse\TestCase\Database;
|
2017-08-29 14:50:31 +00:00
|
|
|
|
2017-08-18 02:36:15 +00:00
|
|
|
use JKingWeb\Arsse\Arsse;
|
2020-04-25 15:42:23 +00:00
|
|
|
use DateTimeImmutable as Date;
|
2017-08-18 02:36:15 +00:00
|
|
|
|
|
|
|
trait SeriesCleanup {
|
2023-02-12 23:30:19 +00:00
|
|
|
protected static $drv;
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
protected function setUpSeriesCleanup(): void {
|
2018-01-01 17:31:42 +00:00
|
|
|
// set up the configuration
|
|
|
|
Arsse::$conf->import([
|
|
|
|
'userSessionTimeout' => "PT1H",
|
|
|
|
'userSessionLifetime' => "PT24H",
|
|
|
|
]);
|
2017-08-18 02:36:15 +00:00
|
|
|
// set up the test data
|
2020-03-11 20:21:42 +00:00
|
|
|
$tz = new \DateTimeZone("UTC");
|
2020-04-25 15:42:23 +00:00
|
|
|
$nowish = (new Date("now - 1 minute", $tz))->format("Y-m-d H:i:s");
|
|
|
|
$yesterday = (new Date("now - 1 day", $tz))->format("Y-m-d H:i:s");
|
|
|
|
$daybefore = (new Date("now - 2 days", $tz))->format("Y-m-d H:i:s");
|
|
|
|
$daysago = (new Date("now - 7 days", $tz))->format("Y-m-d H:i:s");
|
|
|
|
$weeksago = (new Date("now - 21 days", $tz))->format("Y-m-d H:i:s");
|
|
|
|
$soon = (new Date("now + 1 minute", $tz))->format("Y-m-d H:i:s");
|
|
|
|
$faroff = (new Date("now + 1 hour", $tz))->format("Y-m-d H:i:s");
|
2017-08-18 02:36:15 +00:00
|
|
|
$this->data = [
|
|
|
|
'arsse_users' => [
|
2022-06-05 21:41:32 +00:00
|
|
|
'columns' => ["id", "password", "num"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2020-10-30 19:25:22 +00:00
|
|
|
["jane.doe@example.com", "",1],
|
|
|
|
["john.doe@example.com", "",2],
|
2017-08-18 02:36:15 +00:00
|
|
|
],
|
|
|
|
],
|
2017-09-24 16:45:07 +00:00
|
|
|
'arsse_sessions' => [
|
2022-06-05 21:41:32 +00:00
|
|
|
'columns' => ["id", "created", "expires", "user"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2017-09-24 16:45:07 +00:00
|
|
|
["a", $nowish, $faroff, "jane.doe@example.com"], // not expired and recently created, thus kept
|
|
|
|
["b", $nowish, $soon, "jane.doe@example.com"], // not expired and recently created, thus kept
|
|
|
|
["c", $daysago, $soon, "jane.doe@example.com"], // created more than a day ago, thus deleted
|
|
|
|
["d", $nowish, $nowish, "jane.doe@example.com"], // recently created but expired, thus deleted
|
|
|
|
["e", $daysago, $nowish, "jane.doe@example.com"], // created more than a day ago and expired, thus deleted
|
|
|
|
],
|
|
|
|
],
|
2019-03-09 21:23:56 +00:00
|
|
|
'arsse_tokens' => [
|
2022-06-05 21:41:32 +00:00
|
|
|
'columns' => ["id", "class", "user", "expires"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2019-03-09 21:23:56 +00:00
|
|
|
["80fa94c1a11f11e78667001e673b2560", "fever.login", "jane.doe@example.com", $faroff],
|
|
|
|
["27c6de8da13311e78667001e673b2560", "fever.login", "jane.doe@example.com", $weeksago], // expired
|
|
|
|
["ab3b3eb8a13311e78667001e673b2560", "class.class", "jane.doe@example.com", null],
|
|
|
|
["da772f8fa13c11e78667001e673b2560", "class.class", "john.doe@example.com", $soon],
|
|
|
|
],
|
|
|
|
],
|
2020-11-06 22:06:01 +00:00
|
|
|
'arsse_icons' => [
|
2022-06-05 21:41:32 +00:00
|
|
|
'columns' => ["id", "url", "orphaned"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2020-11-07 13:11:06 +00:00
|
|
|
[1,'http://localhost:8000/Icon/PNG',$daybefore],
|
|
|
|
[2,'http://localhost:8000/Icon/GIF',$daybefore],
|
2020-11-06 22:06:01 +00:00
|
|
|
[3,'http://localhost:8000/Icon/SVG1',null],
|
|
|
|
],
|
|
|
|
],
|
2017-08-18 02:36:15 +00:00
|
|
|
'arsse_subscriptions' => [
|
2023-03-10 23:52:33 +00:00
|
|
|
'columns' => ["id", "owner", "url", "size", "icon", "deleted", "modified"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2023-03-10 23:52:33 +00:00
|
|
|
// first two subscriptions are used for article cleanup tests: the latest two articles should be kept
|
|
|
|
[1,'jane.doe@example.com',"http://example.com/1",2,null,0,$daybefore],
|
2023-03-15 21:46:36 +00:00
|
|
|
[2,'john.doe@example.com',"http://example.com/1",2, 1,0,$daybefore],
|
2023-03-10 23:52:33 +00:00
|
|
|
// the other subscriptions are used for subscription cleanup
|
|
|
|
[3,'jane.doe@example.com',"http://example.com/2",0, 2,1,$yesterday],
|
2023-03-15 21:46:36 +00:00
|
|
|
[4,'jane.doe@example.com',"http://example.com/4",0,null,1,$nowish],
|
2023-03-10 23:52:33 +00:00
|
|
|
|
2020-03-01 20:16:50 +00:00
|
|
|
],
|
2017-08-18 02:36:15 +00:00
|
|
|
],
|
|
|
|
'arsse_articles' => [
|
2023-03-14 23:58:33 +00:00
|
|
|
'columns' => ["id", "subscription", "url_title_hash", "url_content_hash", "title_content_hash", "modified", "read", "starred", "hidden", "marked"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2023-03-15 21:46:36 +00:00
|
|
|
[ 1,1,"","","",$weeksago,0,0,0,null], // is the latest article, thus is kept
|
|
|
|
[ 2,1,"","","",$weeksago,0,0,0,null], // is the second latest article, thus is kept
|
|
|
|
[ 3,1,"","","",$weeksago,0,1,0,$weeksago], // is starred by the user, thus is kept
|
|
|
|
[ 4,1,"","","",$weeksago,1,0,0,$yesterday], // does not meet the unread threshold due to a recent mark, thus is kept
|
|
|
|
[ 5,1,"","","",$daysago, 0,0,0,null], // does not meet the unread threshold due to age, thus is kept
|
|
|
|
[ 6,1,"","","",$weeksago,1,0,0,$nowish], // does not meet the read threshold due to a recent mark, thus is kept
|
|
|
|
[ 7,1,"","","",$weeksago,0,0,0,null], // meets the unread threshold without marks, thus is deleted
|
|
|
|
[ 8,1,"","","",$weeksago,1,0,0,$weeksago], // meets the unread threshold even with marks, thus is deleted
|
|
|
|
[ 9,1,"","","",$weeksago,1,0,0,$daysago], // meets the read threshold, thus is deleted
|
|
|
|
[1001,2,"","","",$weeksago,0,0,0,null], // is the latest article, thus is kept
|
|
|
|
[1002,2,"","","",$weeksago,0,0,0,null], // is the second latest article, thus is kept
|
|
|
|
[1003,2,"","","",$weeksago,0,0,0,null], // meets the unread threshold without marks, thus is deleted
|
|
|
|
[1004,2,"","","",$weeksago,0,0,0,null], // meets the unread threshold without marks, thus is deleted
|
|
|
|
[1005,2,"","","",$daysago, 0,0,0,null], // does not meet the unread threshold due to age, thus is kept
|
|
|
|
[1006,2,"","","",$weeksago,1,0,0,$weeksago], // meets the unread threshold even with marks, thus is deleted
|
|
|
|
[1007,2,"","","",$weeksago,0,1,1,$weeksago], // hidden overrides starred, thus is deleted
|
|
|
|
[1008,2,"","","",$weeksago,0,0,0,null], // meets the unread threshold without marks, thus is deleted
|
|
|
|
[1009,2,"","","",$weeksago,0,0,1,$daysago], // meets the read threshold because hidden is equivalent to read, thus is deleted
|
2020-03-01 20:16:50 +00:00
|
|
|
],
|
2017-08-18 02:36:15 +00:00
|
|
|
],
|
|
|
|
'arsse_editions' => [
|
2022-06-05 21:41:32 +00:00
|
|
|
'columns' => ["id", "article"],
|
2022-09-15 14:12:04 +00:00
|
|
|
'rows' => [
|
2017-08-18 02:36:15 +00:00
|
|
|
[1,1],
|
|
|
|
[2,2],
|
|
|
|
[3,3],
|
|
|
|
[4,4],
|
2023-03-10 23:52:33 +00:00
|
|
|
[5,5],
|
|
|
|
[6,6],
|
|
|
|
[7,7],
|
|
|
|
[8,8],
|
|
|
|
[9,9],
|
2017-08-18 02:36:15 +00:00
|
|
|
[201,1],
|
|
|
|
[102,2],
|
2023-03-14 23:58:33 +00:00
|
|
|
[1001,1001],
|
|
|
|
[1002,1002],
|
|
|
|
[1003,1003],
|
|
|
|
[1004,1004],
|
|
|
|
[1005,1005],
|
|
|
|
[1006,1006],
|
|
|
|
[1007,1007],
|
|
|
|
[1008,1008],
|
|
|
|
[1009,1009],
|
|
|
|
[1201,1001],
|
|
|
|
[1102,1002],
|
2020-03-01 20:16:50 +00:00
|
|
|
],
|
2017-08-18 02:36:15 +00:00
|
|
|
],
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
protected function tearDownSeriesCleanup(): void {
|
2018-11-25 05:03:56 +00:00
|
|
|
unset($this->data);
|
|
|
|
}
|
|
|
|
|
2023-03-10 23:52:33 +00:00
|
|
|
public function testCleanUpDeletedSubscriptions(): void {
|
|
|
|
Arsse::$db->subscriptionCleanup();
|
2017-08-18 02:36:15 +00:00
|
|
|
$state = $this->primeExpectations($this->data, [
|
2023-03-14 23:58:33 +00:00
|
|
|
'arsse_subscriptions' => ["id"],
|
2017-08-18 02:36:15 +00:00
|
|
|
]);
|
2023-03-14 23:58:33 +00:00
|
|
|
unset($state['arsse_subscriptions']['rows'][2]);
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
|
|
|
|
2023-03-10 23:52:33 +00:00
|
|
|
public function testCleanUpDeletedSubscriptionsWithUnlimitedRetention(): void {
|
2019-01-21 03:40:49 +00:00
|
|
|
Arsse::$conf->import([
|
|
|
|
'purgeFeeds' => null,
|
|
|
|
]);
|
2023-03-10 23:52:33 +00:00
|
|
|
Arsse::$db->subscriptionCleanup();
|
2019-01-21 03:40:49 +00:00
|
|
|
$state = $this->primeExpectations($this->data, [
|
2023-03-14 23:58:33 +00:00
|
|
|
'arsse_subscriptions' => ["id"],
|
2019-01-21 03:40:49 +00:00
|
|
|
]);
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2019-01-21 03:40:49 +00:00
|
|
|
}
|
|
|
|
|
2020-11-07 13:11:06 +00:00
|
|
|
public function testCleanUpOrphanedIcons(): void {
|
|
|
|
Arsse::$db->iconCleanup();
|
|
|
|
$now = gmdate("Y-m-d H:i:s");
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_icons' => ["id","orphaned"],
|
|
|
|
]);
|
|
|
|
$state['arsse_icons']['rows'][0][1] = null;
|
|
|
|
unset($state['arsse_icons']['rows'][1]);
|
|
|
|
$state['arsse_icons']['rows'][2][1] = $now;
|
|
|
|
$this->compareExpectations(static::$drv, $state);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function testCleanUpOrphanedIconsWithUnlimitedRetention(): void {
|
|
|
|
Arsse::$conf->import([
|
|
|
|
'purgeFeeds' => null,
|
|
|
|
]);
|
|
|
|
Arsse::$db->iconCleanup();
|
|
|
|
$now = gmdate("Y-m-d H:i:s");
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
|
|
|
'arsse_icons' => ["id","orphaned"],
|
|
|
|
]);
|
|
|
|
$state['arsse_icons']['rows'][0][1] = null;
|
|
|
|
$state['arsse_icons']['rows'][2][1] = $now;
|
|
|
|
$this->compareExpectations(static::$drv, $state);
|
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testCleanUpOldArticlesWithStandardRetention(): void {
|
2017-08-18 02:36:15 +00:00
|
|
|
Arsse::$db->articleCleanup();
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
2020-03-01 20:16:50 +00:00
|
|
|
'arsse_articles' => ["id"],
|
2017-08-18 02:36:15 +00:00
|
|
|
]);
|
2023-03-15 21:46:36 +00:00
|
|
|
$deleted = [7, 8, 9, 1003, 1004, 1006, 1007, 1008, 1009];
|
|
|
|
$stop = sizeof($state['arsse_articles']['rows']);
|
|
|
|
for ($a = 0; $a < $stop; $a++) {
|
|
|
|
if (in_array($state['arsse_articles']['rows'][$a][0], $deleted)) {
|
|
|
|
unset($state['arsse_articles']['rows'][$a]);
|
|
|
|
}
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
2018-10-26 18:58:04 +00:00
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testCleanUpOldArticlesWithUnlimitedReadRetention(): void {
|
2019-01-21 03:40:49 +00:00
|
|
|
Arsse::$conf->import([
|
|
|
|
'purgeArticlesRead' => null,
|
|
|
|
]);
|
2017-08-18 02:36:15 +00:00
|
|
|
Arsse::$db->articleCleanup();
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
2020-03-01 20:16:50 +00:00
|
|
|
'arsse_articles' => ["id"],
|
2017-08-18 02:36:15 +00:00
|
|
|
]);
|
2023-03-15 21:46:36 +00:00
|
|
|
$deleted = [7, 8, 1003, 1004, 1006, 1007, 1008];
|
|
|
|
$stop = sizeof($state['arsse_articles']['rows']);
|
|
|
|
for ($a = 0; $a < $stop; $a++) {
|
|
|
|
if (in_array($state['arsse_articles']['rows'][$a][0], $deleted)) {
|
|
|
|
unset($state['arsse_articles']['rows'][$a]);
|
|
|
|
}
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
2018-10-26 18:58:04 +00:00
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testCleanUpOldArticlesWithUnlimitedUnreadRetention(): void {
|
2019-01-21 03:40:49 +00:00
|
|
|
Arsse::$conf->import([
|
|
|
|
'purgeArticlesUnread' => null,
|
|
|
|
]);
|
2017-08-18 02:36:15 +00:00
|
|
|
Arsse::$db->articleCleanup();
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
2020-03-01 20:16:50 +00:00
|
|
|
'arsse_articles' => ["id"],
|
2017-08-18 02:36:15 +00:00
|
|
|
]);
|
2023-03-15 21:46:36 +00:00
|
|
|
$deleted = [8, 9, 1006, 1007, 1009];
|
|
|
|
$stop = sizeof($state['arsse_articles']['rows']);
|
|
|
|
for ($a = 0; $a < $stop; $a++) {
|
|
|
|
if (in_array($state['arsse_articles']['rows'][$a][0], $deleted)) {
|
|
|
|
unset($state['arsse_articles']['rows'][$a]);
|
|
|
|
}
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testCleanUpOldArticlesWithUnlimitedRetention(): void {
|
2019-01-21 03:40:49 +00:00
|
|
|
Arsse::$conf->import([
|
2020-03-01 20:16:50 +00:00
|
|
|
'purgeArticlesRead' => null,
|
2019-01-21 03:40:49 +00:00
|
|
|
'purgeArticlesUnread' => null,
|
|
|
|
]);
|
2017-08-18 02:36:15 +00:00
|
|
|
Arsse::$db->articleCleanup();
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
2020-03-01 20:16:50 +00:00
|
|
|
'arsse_articles' => ["id"],
|
2017-08-18 02:36:15 +00:00
|
|
|
]);
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2017-08-18 02:36:15 +00:00
|
|
|
}
|
2017-09-24 16:45:07 +00:00
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testCleanUpExpiredSessions(): void {
|
2017-09-24 16:45:07 +00:00
|
|
|
Arsse::$db->sessionCleanup();
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
2020-03-01 20:16:50 +00:00
|
|
|
'arsse_sessions' => ["id"],
|
2017-09-24 16:45:07 +00:00
|
|
|
]);
|
|
|
|
foreach ([3,4,5] as $id) {
|
|
|
|
unset($state['arsse_sessions']['rows'][$id - 1]);
|
|
|
|
}
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2017-09-24 16:45:07 +00:00
|
|
|
}
|
2019-03-09 21:23:56 +00:00
|
|
|
|
2020-01-20 18:52:48 +00:00
|
|
|
public function testCleanUpExpiredTokens(): void {
|
2019-03-09 21:23:56 +00:00
|
|
|
Arsse::$db->tokenCleanup();
|
|
|
|
$state = $this->primeExpectations($this->data, [
|
2020-03-01 20:16:50 +00:00
|
|
|
'arsse_tokens' => ["id", "class"],
|
2019-03-09 21:23:56 +00:00
|
|
|
]);
|
|
|
|
foreach ([2] as $id) {
|
|
|
|
unset($state['arsse_tokens']['rows'][$id - 1]);
|
|
|
|
}
|
2019-06-21 22:52:27 +00:00
|
|
|
$this->compareExpectations(static::$drv, $state);
|
2019-03-09 21:23:56 +00:00
|
|
|
}
|
2017-08-29 14:50:31 +00:00
|
|
|
}
|