Repository navigation
refactor(organization-sync): split the contact person sync into steps - #1375
Merged
Merged
Conversation
createOrUpdateContactPersonObject (298 lines, 5 parameters) and updateContactPersonObjectOwner (89 lines, 5 parameters) now take the sync run or the owner as one array and delegate to steps of at most two parameters: find or create the contact, keep its organisation, provision its user, link the user, and stage the owner. The run array holds the caller's stats by reference, so every step still counts into them as it goes, also when a later step throws. Behaviour is unchanged, pinned by a golden test recorded on the old code (23 cases: every branch of both methods, recorded by call and argument name). One redundant check went: the contact object can no longer be null after find-or-create. Assisted-by: ClaudeCode:claude-opus-5-5
…ontact-person-sync
This was referenced Nov 2, 2026
…ontact-person-sync
Contributor
Author
Contributor
Quality Report — ConductionNL/stackiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ❌ | ||||
| check-schema-l10n | ❌ | ||||
| check-l10n-js | ✅ | ||||
| composer | ❌ | ✅ 127/127 | |||
| npm | ❌ | ✅ 807/807 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ✅ 1509/1509 · 20 skipped | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development. |
||||
| Hydra gates | ❌ |
Quality workflow — 2026-11-02 23:22 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
REVIEW: contact person and organisation data. This PR restructures the code that creates contact person objects, keeps their link to the organisation, creates their user accounts and sets their owner. It is meant to change nothing; please review it as such before it merges.
What
OrganizationSyncService::createOrUpdateContactPersonObject(298 lines, McCabe 23, 5 parameters) andupdateContactPersonObjectOwner(89 lines, 5 parameters) are split into named steps:findExistingContactPersoncreateContactPersonObjectcompleteContactPersonensureContactOrganisation, log, and provision a user when it has no usernameprovisionContactUserfindOrganisationEntityForContact,createBackupOrganisationEntity) and create the user only when it is active, elselogSkippedUserCreationcreateUserForContact,linkCreatedUser,saveContactUsernamestageContactOwner,ownerOrganisationpersistContactObjectBoth methods now take one array: the sync run (
organizationUuid,register,contactSchema, and the caller'sstatsheld by reference so every step counts into them as it goes, also when a later step throws), or the owner (userUID,register,contactSchema,organizationUuidOverride). Both are private; their three call sites in this class are updated. Every new step takes at most 2 parameters, McCabe at most 6.What stays exactly as it was, on purpose:
createUserAccount,addUserToOrganizationEntity,setOwnerandsetOrganisation;getActive()fail on null, and that Error still escapes the method as before (it is not an\Exception, so neither catch takes it). Fixing that is a behaviour change for a separate PR;One redundant check went: after find-or-create the contact object can no longer be null (PHPStan flagged
!== nullas always true on the new types).SIG (gate 122 reader, lizard 1.24.3, five-star profile)
No check flips on its own. Together with #1374 (merged), #1376, #1377 and the scope file #1351, php params >=5 reaches 3.28%, under the 3.3% 4-star limit (margin 6 unit lines). This PR carries most of that drop (298 + 89 lines leave the band), so the flip waits on this review.
Verified
tests/Unit/Service/OrganizationSyncContactPersonGoldenTest.php, 23 cases recorded on the old code: every branch of both methods (no email, existing or failed fetch, create with and without organisation, missing organisation entity with a backup that finds none, fails or builds one, inactive, non-true and throwinggetActive(), a generic mapper error, user creation failing, the username or owner save failing, a failed create, no organisation uuid at all, and seven owner-update cases). Each case records every logger, object service (by parameter name, defaults left out), mapper, handler and settings call, the stats and the escaping exception. Re-run plain on old and new: 23/23.prlimit --as=1610612736 timeout 120): 25 of 26 killed over three rounds, the no-op control survived each round (a first-round survivor, the backup entity's return value, led to an e-mail service double so that case completes). The survivor is equivalent:logSkippedUserCreation's null branch cannot be reached, because a null entity already fails inprovisionContactUser.--fail-on-riskyon the golden and the existing OrganizationSyncService test: 29 tests OK, 0 risky.phpunit.xml's server bootstrap, as on development).--fail-on-risky: 1,529 tests, the same 20 errors as development (Doctrine\DBAL\ParameterTypemissing locally), 0 risky.AI disclosure: prepared with Claude Code (claude-opus-5-5) and reviewed by the lane before opening.