Skip to content

fix(sync): apply all InstanceId removes for a recurring series - #97

Merged
ralflang merged 1 commit into
FRAMEWORK_6_0from
fix/instanceid-occurrence-deletes
Jul 28, 2026
Merged

fix(sync): apply all InstanceId removes for a recurring series#97
ralflang merged 1 commit into
FRAMEWORK_6_0from
fix/instanceid-occurrence-deletes

Conversation

@TDannhauer

Copy link
Copy Markdown
Contributor

Summary

  • Keep every EAS 16 InstanceId Remove for the same recurring series (no longer overwrite prior deletes for one ServerEntryId).
  • Resolve iOS Removes that omit ServerEntryId against a single co-batched series Add so the occurrence EXDATE is applied in the same Sync.

Motivation

Deleting a calendar occurrence on iOS often required a second delete: the first Remove arrived without a ServerEntryId (paired with an Add of the series), failed with (null) nicht gefunden, and the Add restored the series without an exception. Separately, deleting several occurrences of one series in one Sync only persisted the last InstanceId because removes were stored as uid => instanceid.

Changes

  • Horde_ActiveSync_Request_Sync: collect instanceid_removes as uid => [InstanceId, ...]; queue orphan InstanceIds when ServerEntryId is empty; after Adds, map orphans to the single new server uid; import all instance deletes (streaming and non-streaming).
  • Horde_ActiveSync_Connector_Importer: correct importMessageDeletion() @param docs (uid => instanceid).
  • Unit tests for multi-InstanceId import, orphan resolution, and deferred import of both.

Test plan

  • vendor/bin/phpunit --bootstrap vendor/autoload.php vendor/horde/activesync/test/unit/Horde/ActiveSync/Request/SyncStreamingTest.php (15 tests)
  • Manual: delete one occurrence of a series on iOS — stays gone after one sync
  • Manual: delete several occurrences of the same series in one go — all stay gone

Store EAS 16 occurrence deletes as uid => [InstanceId, ...] so a Sync
batch that removes several instances of the same series no longer keeps
only the last one. Resolve Removes that omit ServerEntryId against a
single co-batched Add (iOS pattern) so the EXDATE is applied in the
same request instead of requiring a second delete.
@TDannhauer
TDannhauer requested a review from ralflang July 27, 2026 07:41
@github-actions

Copy link
Copy Markdown

🔍 CI Results

Overall: ❌ 12/12 lanes failed

TL;DR: ❌ Quality issues: PHPStan: 243 unique errors in 11 lanes; PHP-CS-Fixer: 29 files.

Summary by PHP Version

PHP dev stable
8.0
8.1
8.2
8.3
8.4
8.5

Quality Metrics

  • PHPUnit: did not run (11 lanes exited non-zero with no test output) ❌
  • PHPStan (advisory): 243 unique errors in 11 lanes ⚠️
  • PHP-CS-Fixer: 29 unique files with issues (of 209 checked) ⚠️
❌ Failed Lanes

php8.0-dev

  • PHPUnit: 0 failures, 0 errors

php8.0-stable

  • PHPUnit: ❌ Setup failed (Composer install failed in /tmp/horde-ci/lanes/php8.0-stable/ActiveSync: Your requirements could not be resolved to an installable set of packages.)
  • PHPStan: ❌ Setup failed (Composer install failed in /tmp/horde-ci/lanes/php8.0-stable/ActiveSync: Your requirements could not be resolved to an installable set of packages.)

php8.1-dev

  • PHPUnit: 0 failures, 0 errors

php8.1-stable

  • PHPUnit: 0 failures, 0 errors

php8.2-dev

  • PHPUnit: 0 failures, 0 errors

php8.2-stable

  • PHPUnit: 0 failures, 0 errors

php8.3-dev

  • PHPUnit: 0 failures, 0 errors

php8.3-stable

  • PHPUnit: 0 failures, 0 errors

php8.4-dev

  • PHPUnit: 0 failures, 0 errors
  • PHP-CS-Fixer: 29 files with issues

php8.4-stable

  • PHPUnit: 0 failures, 0 errors

php8.5-dev

  • PHPUnit: 0 failures, 0 errors

php8.5-stable

  • PHPUnit: 0 failures, 0 errors

CI powered by horde-componentsView full results

@ralflang
ralflang merged commit 48e630a into FRAMEWORK_6_0 Jul 28, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants