Skip to content

[access] refactor(profile-fields): split ProfileFieldService definitions, own values, visibility, search and LDAP sync into named steps - #1079

Open
rubenvdlinde wants to merge 2 commits into
developmentfrom
quality/i40-profilefields-steps
Open

rubenvdlinde wants to merge 2 commits into
developmentfrom
quality/i40-profilefields-steps

Conversation

@rubenvdlinde

@rubenvdlinde rubenvdlinde commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

What changed

Seven ProfileFieldService units read as named steps; every public signature is unchanged.

  • Definitions: validateDefinition → validKey → definitionFrom (label, then type, source and visibility checked in the original order, via validLabel and oneOf) → withCheckedLdapAttribute.
  • Own values: saveOwnValues → definitionsByKey → cleanOwnValues (every value is still checked before anything is written; read-only fields are still skipped) → writes. cleanValues → valueItems, cleanItem, itemText, with the same messages.
  • Visibility: visibleFieldsFor keeps its guards and hands the widget definitions and the viewer's canSee check to a new ProfileFieldListing, a small final run object built for this one listing (fieldsByPerson, fieldsOf).
  • Search: findMatchingUserIds → searchableDefinitions; scopeAllows gives the same answer for every scope / viewer / owner with two checks instead of three.
  • LDAP: syncLdapFields keeps its guards, then syncFromLdap (ldapFieldValues), still counting the fields synced before a directory failure.

Allowed and refused outcomes are unchanged: the same people and fields are visible to the same viewers, the same searches match, and the same saves and definitions are refused with the same messages.

Characterisation tests

tests/Unit/Service/ProfileFieldServiceAccessGoldenTest.php was committed first, against the old code, and passes before and after: the normalised definition and the LDAP variant, every invalid definition with its message and check order; saved own values (cleaned, de-duplicated, read-only skipped, cleared) and every refused save leaving the stored value in place; visible fields for a group member, another group, a person without groups, an anonymous viewer and no people; the search across group-only, everyone, LDAP, hidden-from-widget and mirrored standard fields with private and federated scopes; every scope case; and every LDAP sync outcome including a mid-sync directory failure. Mutation check: letting every scope through on the old code turned the scope and search goldens red; restored before committing.

What ran

  • vendor/bin/phpunit -c phpunit.xml --no-coverage tests/Unit: 2778 tests OK (13 skipped, as on development).
  • vendor/bin/phpcs and vendor/bin/phpstan analyse on the touched lib files: clean.
  • vendor/bin/phpmd on ProfileFieldService: one new finding, TooManyMethods (30 methods against a limit of 25), the cost of turning long methods into named private steps; composer phpmd is already red on development for other classes.

Figures (touched files lib/Service/ProfileFieldService.php, lib/Service/ProfileFieldListing.php)

before after
units over complexity 5 7 units, 167 lines 0
units over 15 lines of code 9 units, 222 lines 3 units, 64 lines (untouched methods)
units over 2 parameters 5 units, 47 lines 5 units, 44 lines

ProfileFieldListing depends on nothing in the app; only ProfileFieldService depends on it. App-wide: unit complexity 4.02 → 4.10, unit size 3.40 → 3.42.

Maintainability floor: compare against development holds.

AI-assisted: prepared with Claude Code (claude-opus-5-5); reviewed by a maintainer before merge.


Generated by Claude Code

…es and definitions before the split

Assisted-by: ClaudeCode:claude-opus-5-5
…values, visibility, search and LDAP sync into named steps

Assisted-by: ClaudeCode:claude-opus-5-5
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