Repository navigation
Conversation
HachemJ
added a commit
to HachemJ/Loris
that referenced
this pull request
Oct 13, 2026
This was referenced Oct 22, 2026
HachemJ
force-pushed
the
ReworkIdentifierStructure
branch
from
October 27, 2026 15:20
609b334 to
c31e7df
Compare
This branch has not been deployed
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.
Brief summary of changes
This PR adds the database structure for the candidate identifier rework discussed in #9036.
It introduces three tables:
candidate_identifier_typesStores the configuration for each identifier type.candidate_identifier_types_project_relLinks identifier types to projects.candidate_identifiersStores the identifier values assigned to candidates.It also adds a migration script,
tools/single_use/migrate_candidate_identifiers.php, to migrate the existing PSCID and ExternalID configuration fromconfig.xmlinto the new tables.Existing identifier values and
config.xmlare left unchanged.This is the first PR in the candidate identifier rework. The identifier generation and validation logic is added in #11212, and the REST API changes are added in #11253.
Database structure and design decisions
Identifier types
candidate_identifier_typesstores the configuration for each identifier type.CandidateIdentifierTypeIDNameFormatIsRequiredIsUniqueAutoGenerateAllowMultiplepermIDFor example, PSCID can be configured as required, unique, automatically generated, and limited to one value per candidate. Other identifiers can be optional, manually entered, or allow multiple values.
Projects and permissions
candidate_identifier_types_project_rellinks identifier types to the projects where they can be used. An identifier type can belong to multiple projects.For visibility, I used the existing LORIS permission system instead of adding a separate
Visiblesetting.The optional permission is stored in
permID. Each identifier type can have one permission, but the same permission can be assigned to multiple identifier types.If a permission is configured, users need that permission to view the identifier type. Otherwise, anyone with access to the candidate should be able to view it.
Permission checks are handled in the application implementation rather than in this PR.
Candidate identifiers
candidate_identifiersstores the identifier values assigned to candidates.CandidateIdentifierIDCandidateIDCandidateIdentifierTypeIDValueI added a separate
CandidateIdentifierIDprimary key because a candidate can have multiple values of the same identifier type whenAllowMultipleis enabled.The
AllowMultipleandIsUniquesettings are enforced in the application rather than through database constraints.For example, a unique constraint on
(CandidateID, CandidateIdentifierTypeID)would prevent multiple values for all identifier types, including those whereAllowMultipleis enabled.This means direct database inserts could bypass these rules, so the application needs to check the identifier type configuration when adding or updating values.
Deletion behavior
Identifier values are deleted when their candidate is deleted.
I chose not to cascade deletion from identifier types to their values. Accidentally deleting an identifier type, such as PSCID, should not also delete all the stored values.
Instead, the foreign key prevents an identifier type from being deleted while values still reference it.
Project relationships are deleted when their related configuration is deleted, since they only store associations.
If a permission is deleted,
permIDis set toNULLrather than deleting the identifier type.Identifier formats
Identifier formats are now stored as templates in the
Formatcolumn, replacing the previousstructureandgenerationsettings inconfig.xml.The templates define the identifier structure and, when
AutoGenerateis enabled, how the value should be generated.The logic for interpreting these templates is implemented in #11212.
Identifier template syntax
Templates can contain literal text and placeholders enclosed in curly braces.
For example:
The supported placeholders are:
{SITE:ALIAS}{PROJECT:ALIAS}{SEQUENCE:N}N{RANDOM:N}N{NUMERIC:N}Ndigits{ALPHA:N}Nletters{ALPHANUMERIC:N}Nalphanumeric charactersSEQUENCEandRANDOMalso support:FORMAT—numeric,alpha, oralphanumeric(defaults tonumeric).PADDING— character used for left-padding (defaults to0orA, depending on the alphabet).MIN— minimum generator value.MAX— maximum generator value.An automatically generated identifier uses one
SEQUENCEorRANDOMplaceholder, which can be combined with literal text, site aliases, and project aliases.When
AutoGenerateis disabled, the identifier is entered manually and validated against the template. TheNUMERIC,ALPHA, andALPHANUMERICplaceholders are used for validation only.Testing instructions (if applicable)
Apply the SQL patch and check that the three new tables are created.
Run the migration script:
Check that PSCID and ExternalID are added to
candidate_identifier_typeswith the expected formats and settings.Verify that the project relationships are migrated correctly.
Confirm that
config.xmland the existing PSCID and ExternalID values in the candidate table are unchanged.