aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/dav/lib/CalDAV/CalDavBackend.php13
-rw-r--r--apps/dav/lib/CardDAV/CardDavBackend.php13
-rw-r--r--apps/dav/tests/unit/CalDAV/CalDavBackendTest.php74
-rw-r--r--apps/dav/tests/unit/CardDAV/CardDavBackendTest.php41
-rw-r--r--core/Command/Config/App/DeleteConfig.php10
-rw-r--r--core/Command/Config/App/GetConfig.php7
-rw-r--r--core/Command/Config/App/SetConfig.php7
-rw-r--r--core/Command/Config/Import.php6
-rw-r--r--core/Command/Config/ListConfigs.php9
-rw-r--r--core/Command/Config/System/Base.php7
-rw-r--r--core/Command/Config/System/DeleteConfig.php4
-rw-r--r--core/Command/Config/System/GetConfig.php4
-rw-r--r--core/Command/Config/System/SetConfig.php4
-rw-r--r--core/Command/Group/Add.php7
-rw-r--r--core/Command/Group/AddUser.php10
-rw-r--r--core/Command/Group/Delete.php7
-rw-r--r--core/Command/Group/Info.php7
-rw-r--r--core/Command/Group/ListCommand.php7
-rw-r--r--core/Command/Group/RemoveUser.php10
19 files changed, 183 insertions, 64 deletions
diff --git a/apps/dav/lib/CalDAV/CalDavBackend.php b/apps/dav/lib/CalDAV/CalDavBackend.php
index 1cdb705ac92..94fe9acf356 100644
--- a/apps/dav/lib/CalDAV/CalDavBackend.php
+++ b/apps/dav/lib/CalDAV/CalDavBackend.php
@@ -3134,10 +3134,19 @@ class CalDavBackend extends AbstractBackend implements SyncSupport, Subscription
if ($keep < 0) {
throw new \InvalidArgumentException();
}
+
+ $query = $this->db->getQueryBuilder();
+ $query->select($query->func()->max('id'))
+ ->from('calendarchanges');
+
+ $maxId = $query->executeQuery()->fetchOne();
+ if (!$maxId || $maxId < $keep) {
+ return 0;
+ }
+
$query = $this->db->getQueryBuilder();
$query->delete('calendarchanges')
- ->orderBy('id', 'DESC')
- ->setFirstResult($keep);
+ ->where($query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
return $query->executeStatement();
}
diff --git a/apps/dav/lib/CardDAV/CardDavBackend.php b/apps/dav/lib/CardDAV/CardDavBackend.php
index 4e4d64f6f72..1be1ce3f18f 100644
--- a/apps/dav/lib/CardDAV/CardDavBackend.php
+++ b/apps/dav/lib/CardDAV/CardDavBackend.php
@@ -1399,10 +1399,19 @@ class CardDavBackend implements BackendInterface, SyncSupport {
if ($keep < 0) {
throw new \InvalidArgumentException();
}
+
+ $query = $this->db->getQueryBuilder();
+ $query->select($query->func()->max('id'))
+ ->from('addressbookchanges');
+
+ $maxId = $query->executeQuery()->fetchOne();
+ if (!$maxId || $maxId < $keep) {
+ return 0;
+ }
+
$query = $this->db->getQueryBuilder();
$query->delete('addressbookchanges')
- ->orderBy('id', 'DESC')
- ->setFirstResult($keep);
+ ->where($query->expr()->lte('id', $query->createNamedParameter($maxId - $keep, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
return $query->executeStatement();
}
diff --git a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
index 69096d0cfbb..0fdd617943b 100644
--- a/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
+++ b/apps/dav/tests/unit/CalDAV/CalDavBackendTest.php
@@ -1291,6 +1291,8 @@ EOD;
*/
public function testPruneOutdatedSyncTokens(): void {
$calendarId = $this->createTestCalendar();
+ $changes = $this->backend->getChangesForCalendar($calendarId, '', 1);
+ $syncToken = $changes['syncToken'];
$uri = static::getUniqueID('calobj');
$calData = <<<EOD
@@ -1333,9 +1335,79 @@ EOD;
$deleted = $this->backend->pruneOutdatedSyncTokens(0);
// At least one from the object creation and one from the object update
$this->assertGreaterThanOrEqual(2, $deleted);
- $changes = $this->backend->getChangesForCalendar($calendarId, '5', 1);
+ $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 1);
$this->assertEmpty($changes['added']);
$this->assertEmpty($changes['modified']);
$this->assertEmpty($changes['deleted']);
+
+ // Test that objects remain
+
+ // Currently changes are empty
+ $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100);
+ $this->assertEquals(0, count($changes['added'] + $changes['modified'] + $changes['deleted']));
+
+ // Create card
+ $uri = static::getUniqueID('calobj');
+$calData = <<<EOD
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:Nextcloud Calendar
+BEGIN:VEVENT
+CREATED;VALUE=DATE-TIME:20230910T125139Z
+UID:47d15e3ec9
+LAST-MODIFIED;VALUE=DATE-TIME:20230910T125139Z
+DTSTAMP;VALUE=DATE-TIME:20230910T125139Z
+SUMMARY:Test Event
+DTSTART;VALUE=DATE-TIME:20230912T130000Z
+DTEND;VALUE=DATE-TIME:20230912T140000Z
+CLASS:PUBLIC
+END:VEVENT
+END:VCALENDAR
+EOD;
+ $this->backend->createCalendarObject($calendarId, $uri, $calData);
+
+ // We now have one add
+ $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100);
+ $this->assertEquals(1, count($changes['added']));
+ $this->assertEmpty($changes['modified']);
+ $this->assertEmpty($changes['deleted']);
+
+ // update the card
+ $calData = <<<'EOD'
+BEGIN:VCALENDAR
+VERSION:2.0
+PRODID:Nextcloud Calendar
+BEGIN:VEVENT
+CREATED;VALUE=DATE-TIME:20230910T125139Z
+UID:47d15e3ec9
+LAST-MODIFIED;VALUE=DATE-TIME:20230910T125139Z
+DTSTAMP;VALUE=DATE-TIME:20230910T125139Z
+SUMMARY:123 Event 🙈
+DTSTART;VALUE=DATE-TIME:20230912T130000Z
+DTEND;VALUE=DATE-TIME:20230912T140000Z
+ATTENDEE;CN=test:mailto:foo@bar.com
+END:VEVENT
+END:VCALENDAR
+EOD;
+ $this->backend->updateCalendarObject($calendarId, $uri, $calData);
+
+ // One add, one modify, but shortened to modify
+ $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100);
+ $this->assertEmpty($changes['added']);
+ $this->assertEquals(1, count($changes['modified']));
+ $this->assertEmpty($changes['deleted']);
+
+ // Delete all but last change
+ $deleted = $this->backend->pruneOutdatedSyncTokens(1);
+ $this->assertEquals(1, $deleted); // We had two changes before, now one
+
+ // Only update should remain
+ $changes = $this->backend->getChangesForCalendar($calendarId, $syncToken, 100);
+ $this->assertEmpty($changes['added']);
+ $this->assertEquals(1, count($changes['modified']));
+ $this->assertEmpty($changes['deleted']);
+
+ // Check that no crash occurs when prune is called without current changes
+ $deleted = $this->backend->pruneOutdatedSyncTokens(1);
}
}
diff --git a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
index adf64ef82b0..425e7c44ba7 100644
--- a/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
+++ b/apps/dav/tests/unit/CardDAV/CardDavBackendTest.php
@@ -853,15 +853,54 @@ class CardDavBackendTest extends TestCase {
*/
public function testPruneOutdatedSyncTokens(): void {
$addressBookId = $this->backend->createAddressBook(self::UNIT_TEST_USER, 'Example', []);
+ $changes = $this->backend->getChangesForAddressBook($addressBookId, '', 1);
+ $syncToken = $changes['syncToken'];
+
$uri = $this->getUniqueID('card');
$this->backend->createCard($addressBookId, $uri, $this->vcardTest0);
$this->backend->updateCard($addressBookId, $uri, $this->vcardTest1);
$deleted = $this->backend->pruneOutdatedSyncTokens(0);
// At least one from the object creation and one from the object update
$this->assertGreaterThanOrEqual(2, $deleted);
- $changes = $this->backend->getChangesForAddressBook($addressBookId, '5', 1);
+ $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 1);
$this->assertEmpty($changes['added']);
$this->assertEmpty($changes['modified']);
$this->assertEmpty($changes['deleted']);
+
+ // Test that objects remain
+
+ // Currently changes are empty
+ $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100);
+ $this->assertEquals(0, count($changes['added'] + $changes['modified'] + $changes['deleted']));
+
+ // Create card
+ $uri = $this->getUniqueID('card');
+ $this->backend->createCard($addressBookId, $uri, $this->vcardTest0);
+ // We now have one add
+ $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100);
+ $this->assertEquals(1, count($changes['added']));
+ $this->assertEmpty($changes['modified']);
+ $this->assertEmpty($changes['deleted']);
+
+ // Update card
+ $this->backend->updateCard($addressBookId, $uri, $this->vcardTest1);
+ // One add, one modify, but shortened to modify
+ $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100);
+ $this->assertEmpty($changes['added']);
+ $this->assertEquals(1, count($changes['modified']));
+ $this->assertEmpty($changes['deleted']);
+
+ // Delete all but last change
+ $deleted = $this->backend->pruneOutdatedSyncTokens(1);
+ $this->assertEquals(1, $deleted); // We had two changes before, now one
+
+ // Only update should remain
+ $changes = $this->backend->getChangesForAddressBook($addressBookId, $syncToken, 100);
+ $this->assertEmpty($changes['added']);
+ $this->assertEquals(1, count($changes['modified']));
+ $this->assertEmpty($changes['deleted']);
+
+ // Check that no crash occurs when prune is called without current changes
+ $deleted = $this->backend->pruneOutdatedSyncTokens(1);
}
}
diff --git a/core/Command/Config/App/DeleteConfig.php b/core/Command/Config/App/DeleteConfig.php
index 0da1e965bd0..b77f27ccd07 100644
--- a/core/Command/Config/App/DeleteConfig.php
+++ b/core/Command/Config/App/DeleteConfig.php
@@ -28,14 +28,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class DeleteConfig extends Base {
- protected IConfig $config;
-
- /**
- * @param IConfig $config
- */
- public function __construct(IConfig $config) {
+ public function __construct(
+ protected IConfig $config,
+ ) {
parent::__construct();
- $this->config = $config;
}
protected function configure() {
diff --git a/core/Command/Config/App/GetConfig.php b/core/Command/Config/App/GetConfig.php
index 7fdff2be732..96078b63e90 100644
--- a/core/Command/Config/App/GetConfig.php
+++ b/core/Command/Config/App/GetConfig.php
@@ -28,11 +28,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class GetConfig extends Base {
- protected IConfig $config;
-
- public function __construct(IConfig $config) {
+ public function __construct(
+ protected IConfig $config,
+ ) {
parent::__construct();
- $this->config = $config;
}
protected function configure() {
diff --git a/core/Command/Config/App/SetConfig.php b/core/Command/Config/App/SetConfig.php
index 89a5f6ba5d1..99746246b85 100644
--- a/core/Command/Config/App/SetConfig.php
+++ b/core/Command/Config/App/SetConfig.php
@@ -28,11 +28,10 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class SetConfig extends Base {
- protected IConfig $config;
-
- public function __construct(IConfig $config) {
+ public function __construct(
+ protected IConfig $config,
+ ) {
parent::__construct();
- $this->config = $config;
}
protected function configure() {
diff --git a/core/Command/Config/Import.php b/core/Command/Config/Import.php
index 227c909038c..b8431c8c295 100644
--- a/core/Command/Config/Import.php
+++ b/core/Command/Config/Import.php
@@ -35,11 +35,11 @@ use Symfony\Component\Console\Output\OutputInterface;
class Import extends Command implements CompletionAwareInterface {
protected array $validRootKeys = ['system', 'apps'];
- protected IConfig $config;
- public function __construct(IConfig $config) {
+ public function __construct(
+ protected IConfig $config,
+ ) {
parent::__construct();
- $this->config = $config;
}
protected function configure() {
diff --git a/core/Command/Config/ListConfigs.php b/core/Command/Config/ListConfigs.php
index dd8fad72d7c..4adb0a9df5b 100644
--- a/core/Command/Config/ListConfigs.php
+++ b/core/Command/Config/ListConfigs.php
@@ -33,13 +33,12 @@ use Symfony\Component\Console\Output\OutputInterface;
class ListConfigs extends Base {
protected string $defaultOutputFormat = self::OUTPUT_FORMAT_JSON_PRETTY;
- protected SystemConfig $systemConfig;
- protected IAppConfig $appConfig;
- public function __construct(SystemConfig $systemConfig, IAppConfig $appConfig) {
+ public function __construct(
+ protected SystemConfig $systemConfig,
+ protected IAppConfig $appConfig,
+ ) {
parent::__construct();
- $this->systemConfig = $systemConfig;
- $this->appConfig = $appConfig;
}
protected function configure() {
diff --git a/core/Command/Config/System/Base.php b/core/Command/Config/System/Base.php
index 18bc9cb7ca0..09ec456f6a4 100644
--- a/core/Command/Config/System/Base.php
+++ b/core/Command/Config/System/Base.php
@@ -26,11 +26,10 @@ use OC\SystemConfig;
use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
abstract class Base extends \OC\Core\Command\Base {
- protected SystemConfig $systemConfig;
-
- public function __construct(SystemConfig $systemConfig) {
+ public function __construct(
+ protected SystemConfig $systemConfig,
+ ) {
parent::__construct();
- $this->systemConfig = $systemConfig;
}
/**
diff --git a/core/Command/Config/System/DeleteConfig.php b/core/Command/Config/System/DeleteConfig.php
index f4d49ba8f51..f6650e7d6d3 100644
--- a/core/Command/Config/System/DeleteConfig.php
+++ b/core/Command/Config/System/DeleteConfig.php
@@ -30,7 +30,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class DeleteConfig extends Base {
- public function __construct(SystemConfig $systemConfig) {
+ public function __construct(
+ SystemConfig $systemConfig,
+ ) {
parent::__construct($systemConfig);
}
diff --git a/core/Command/Config/System/GetConfig.php b/core/Command/Config/System/GetConfig.php
index 01bbf82d5d1..ab5b884fda4 100644
--- a/core/Command/Config/System/GetConfig.php
+++ b/core/Command/Config/System/GetConfig.php
@@ -29,7 +29,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class GetConfig extends Base {
- public function __construct(SystemConfig $systemConfig) {
+ public function __construct(
+ SystemConfig $systemConfig,
+ ) {
parent::__construct($systemConfig);
}
diff --git a/core/Command/Config/System/SetConfig.php b/core/Command/Config/System/SetConfig.php
index 01a1999bcf9..ba5265a84d7 100644
--- a/core/Command/Config/System/SetConfig.php
+++ b/core/Command/Config/System/SetConfig.php
@@ -32,7 +32,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class SetConfig extends Base {
- public function __construct(SystemConfig $systemConfig) {
+ public function __construct(
+ SystemConfig $systemConfig,
+ ) {
parent::__construct($systemConfig);
}
diff --git a/core/Command/Group/Add.php b/core/Command/Group/Add.php
index d205cef0696..40502762e95 100644
--- a/core/Command/Group/Add.php
+++ b/core/Command/Group/Add.php
@@ -36,10 +36,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Add extends Base {
- protected IGroupManager $groupManager;
-
- public function __construct(IGroupManager $groupManager) {
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Group/AddUser.php b/core/Command/Group/AddUser.php
index 6638bcd4c6d..a66d2898ef9 100644
--- a/core/Command/Group/AddUser.php
+++ b/core/Command/Group/AddUser.php
@@ -34,12 +34,10 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class AddUser extends Base {
- protected IUserManager $userManager;
- protected IGroupManager $groupManager;
-
- public function __construct(IUserManager $userManager, IGroupManager $groupManager) {
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Group/Delete.php b/core/Command/Group/Delete.php
index fd1074d6f61..c7cbf0aa0f6 100644
--- a/core/Command/Group/Delete.php
+++ b/core/Command/Group/Delete.php
@@ -35,10 +35,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class Delete extends Base {
- protected IGroupManager $groupManager;
-
- public function __construct(IGroupManager $groupManager) {
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Group/Info.php b/core/Command/Group/Info.php
index dc475581ac5..1dab56e1a89 100644
--- a/core/Command/Group/Info.php
+++ b/core/Command/Group/Info.php
@@ -35,10 +35,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Info extends Base {
- protected IGroupManager $groupManager;
-
- public function __construct(IGroupManager $groupManager) {
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Group/ListCommand.php b/core/Command/Group/ListCommand.php
index 0285cc05dcd..22ce4cb0317 100644
--- a/core/Command/Group/ListCommand.php
+++ b/core/Command/Group/ListCommand.php
@@ -32,10 +32,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ListCommand extends Base {
- protected IGroupManager $groupManager;
-
- public function __construct(IGroupManager $groupManager) {
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}
diff --git a/core/Command/Group/RemoveUser.php b/core/Command/Group/RemoveUser.php
index c7b3a2d84e7..6c7d4ce4d84 100644
--- a/core/Command/Group/RemoveUser.php
+++ b/core/Command/Group/RemoveUser.php
@@ -34,12 +34,10 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class RemoveUser extends Base {
- protected IUserManager $userManager;
- protected IGroupManager $groupManager;
-
- public function __construct(IUserManager $userManager, IGroupManager $groupManager) {
- $this->userManager = $userManager;
- $this->groupManager = $groupManager;
+ public function __construct(
+ protected IUserManager $userManager,
+ protected IGroupManager $groupManager,
+ ) {
parent::__construct();
}