-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
266 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
240 changes: 240 additions & 0 deletions
240
app/plugins/Transmogrify/src/Lib/Traits/ActionCodeMapperTrait.php
This file contains 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,240 @@ | ||
| <?php | ||
|
|
||
| /** | ||
| * COmanage Registry Transmogrify Command / Action Code Mapper Trait | ||
| * | ||
| * Portions licensed to the University Corporation for Advanced Internet | ||
| * Development, Inc. ("UCAID") under one or more contributor license agreements. | ||
| * See the NOTICE file distributed with this work for additional information | ||
| * regarding copyright ownership. | ||
| * | ||
| * UCAID licenses this file to you under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with the | ||
| * License. You may obtain a copy of the License at: | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| * | ||
| * @link https://www.internet2.edu/comanage COmanage Project | ||
| * @package registry | ||
| * @since COmanage Registry v5.2.0 | ||
| * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) | ||
| */ | ||
|
|
||
| declare(strict_types = 1); | ||
|
|
||
| namespace Transmogrify\Lib\Traits; | ||
|
|
||
| trait ActionCodeMapperTrait | ||
| { | ||
| /** | ||
| * v4 ActionEnum codes that map directly to v5 ActionEnum codes (same code). | ||
| * | ||
| * Keys are v4 right-hand codes, values are v5 right-hand codes. | ||
| * | ||
| * @var array<string, string> | ||
| */ | ||
| protected const ACTION_CODE_DIRECT_MAP = [ | ||
| // Authenticators | ||
| 'EAUT' => 'EAUT', // AuthenticatorEdited | ||
|
|
||
| // Comments | ||
| 'CMNT' => 'CMNT', // CommentAdded | ||
|
|
||
| 'EMLV' => 'EMLV', // EmailAddressVerified -> EmailVerified | ||
| 'EMLS' => 'EMLS', // EmailAddressVerifyReqSent -> EmailVerifyCodeSent | ||
|
|
||
| // External Identity / Login env | ||
| 'EOIE' => 'EOIE', // OrgIdEditedLoginEnv -> ExternalIdentityLoginUpdate | ||
|
|
||
| // Groups | ||
| 'ACGR' => 'ACGR', // CoGroupAdded -> GroupAdded | ||
| 'DCGR' => 'DCGR', // CoGroupDeleted -> GroupDeleted | ||
| 'ECGR' => 'ECGR', // CoGroupEdited -> GroupEdited | ||
|
|
||
| // Group Members | ||
| 'ACGM' => 'ACGM', // CoGroupMemberAdded -> GroupMemberAdded | ||
| 'DCGM' => 'DCGM', // CoGroupMemberDeleted -> GroupMemberDeleted | ||
| 'ECGM' => 'ECGM', // CoGroupMemberEdited -> GroupMemberEdited | ||
|
|
||
| // Identifiers / Matching | ||
| 'AIDA' => 'AIDA', // IdentifierAutoAssigned | ||
| 'UMAT' => 'UMAT', // MatchAttributesUpdated | ||
|
|
||
| // Names | ||
| 'PNAM' => 'PNAM', // NamePrimary | ||
|
|
||
| // Notifications | ||
| 'NOTA' => 'NOTA', // NotificationAcknowledged | ||
| 'NOTX' => 'NOTX', // NotificationCanceled | ||
| 'NOTD' => 'NOTD', // NotificationDelivered | ||
| 'NOTR' => 'NOTR', // NotificationResolved | ||
|
|
||
| // Person pipeline | ||
| 'ACPP' => 'ACPP', // CoPersonAddedPetition -> PersonAddedPetition | ||
| 'ACPL' => 'ACPL', // CoPersonAddedPipeline -> PersonAddedPipeline | ||
| 'MCPL' => 'MCPL', // CoPersonMatchedPipeline -> PersonMatchedPipeline | ||
|
|
||
| // Person status | ||
| 'RCPS' => 'RCPS', // CoPersonStatusRecalculated -> PersonStatusRecalculated | ||
|
|
||
| // Petitions | ||
| 'CPPC' => 'CPPC', // CoPetitionCreated -> PetitionCreated | ||
| 'CPUP' => 'CPUP', // CoPetitionUpdated -> PetitionUpdated | ||
|
|
||
| // Reference ID | ||
| 'OIDR' => 'OIDR', // ReferenceIdentifierObtained | ||
| ]; | ||
|
|
||
| /** | ||
| * v4 codes that map to v5 ActionEnum with a changed code. | ||
| * | ||
| * @var array<string, string> | ||
| */ | ||
| protected const ACTION_CODE_RENAMED_MAP = [ | ||
| // CoPersonRoleRelinked (LCRM) -> PersonRoleRelinked (LCPR) | ||
| 'LCRM' => 'LCPR', | ||
| ]; | ||
|
|
||
| /** | ||
| * v4 ActionEnum codes that moved to PetitionActionEnum in v5. | ||
| * | ||
| * Keys are v4 codes, values are v5 PetitionActionEnum codes. | ||
| * | ||
| * @var array<string, string> | ||
| */ | ||
| protected const ACTION_CODE_PETITION_MAP = [ | ||
| // Invitations moved into PetitionActionEnum | ||
| 'INVC' => 'IC', // InvitationConfirmed -> Accepted | ||
| 'INVD' => 'PX', // InvitationDeclined -> Declined | ||
| 'INVV' => 'IV', // InvitationViewed -> InvitationViewed | ||
| // 'INVE' => null, // InvitationExpired (no explicit equivalent) | ||
| // 'INVS' => null, // InvitationSent (no explicit equivalent) | ||
| ]; | ||
|
|
||
| /** | ||
| * Optional/opinionated mappings to collapse specific attribute events (names) | ||
| * into v5’s generic MVEA* events. Disabled by default for correctness. | ||
| * | ||
| * @var array<string, string> | ||
| */ | ||
| protected const ACTION_CODE_OPTIONAL_OPINIONATED_MAP = [ | ||
| // Names -> generic Multi-Valued Extended Attribute events | ||
| 'ANAM' => 'AMVE', // NameAdded -> MVEAAdded | ||
| 'ENAM' => 'EMVE', // NameEdited -> MVEAEdited | ||
| 'DNAM' => 'DMVE', // NameDeleted -> MVEADeleted | ||
| ]; | ||
|
|
||
| /** | ||
| * Map a v4 ActionEnum right-hand code to v5. | ||
| * | ||
| * Returns: | ||
| * - enum: 'ActionEnum' | 'PetitionActionEnum' | null | ||
| * - code: string|null | ||
| * | ||
| * When enum is null, there is no v5 equivalent; callers can log/skip. | ||
| * | ||
| * @param string $v4Code | ||
| * @param bool $enableOpinionated Enable optional generalized mappings (default=false) | ||
| * @return array{enum: string|null, code: string|null} | ||
| */ | ||
| protected function mapActionCode(string $v4Code, bool $enableOpinionated = false): array | ||
| { | ||
| $key = strtoupper(trim($v4Code)); | ||
|
|
||
| if (isset(self::ACTION_CODE_DIRECT_MAP[$key])) { | ||
| return ['enum' => 'ActionEnum', 'code' => self::ACTION_CODE_DIRECT_MAP[$key]]; | ||
| } | ||
|
|
||
| if (isset(self::ACTION_CODE_RENAMED_MAP[$key])) { | ||
| return ['enum' => 'ActionEnum', 'code' => self::ACTION_CODE_RENAMED_MAP[$key]]; | ||
| } | ||
|
|
||
| if (isset(self::ACTION_CODE_PETITION_MAP[$key])) { | ||
| return ['enum' => 'PetitionActionEnum', 'code' => self::ACTION_CODE_PETITION_MAP[$key]]; | ||
| } | ||
|
|
||
| if ($enableOpinionated && isset(self::ACTION_CODE_OPTIONAL_OPINIONATED_MAP[$key])) { | ||
| return ['enum' => 'ActionEnum', 'code' => self::ACTION_CODE_OPTIONAL_OPINIONATED_MAP[$key]]; | ||
| } | ||
|
|
||
| return ['enum' => null, 'code' => null]; | ||
| } | ||
|
|
||
| /** | ||
| * Convenience: map from a row array. Tries 'action' first, then 'action_code'. | ||
| * | ||
| * @param array $row | ||
| * @param bool $enableOpinionated | ||
| * @return array{enum: string|null, code: string|null} | ||
| */ | ||
| protected function mapActionFromRow(array $row, bool $enableOpinionated = false): array | ||
| { | ||
| $code = null; | ||
|
|
||
| if (isset($row['action']) && is_string($row['action'])) { | ||
| $code = $row['action']; | ||
| } | ||
|
|
||
| if ($code === null) { | ||
| return ['enum' => null, 'code' => null]; | ||
| } | ||
|
|
||
| return $this->mapActionCode($code, $enableOpinionated); | ||
| } | ||
|
|
||
| /** | ||
| * Map a cm_co_notifications row’s action code to a v5 ActionEnum code. | ||
| * For notifications we only accept ActionEnum; PetitionActionEnum mappings return null. | ||
| */ | ||
| protected function mapNotificationAction(array $row): ?string | ||
| { | ||
| $m = $this->mapActionFromRow($row); | ||
|
|
||
| if ($m['enum'] === 'ActionEnum') { | ||
| return $m['code']; | ||
| } | ||
|
|
||
| // No ActionEnum equivalent (eg, invitation events that moved to PetitionActionEnum) | ||
| $rawCode = null; | ||
| if (isset($row['action']) && is_string($row['action'])) { | ||
| $rawCode = $row['action']; | ||
| } | ||
|
|
||
| if ($rawCode !== null && isset($this->cmdPrinter)) { | ||
| $unmapped = $this->listUnmappedActionCodes([$rawCode], false); | ||
| if (!empty($unmapped)) { | ||
| $this->cmdPrinter->warning(sprintf('Skipping notification with unmapped action code: %s', $unmapped[0])); | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Report which v4 action codes won’t map under current settings. | ||
| * | ||
| * @param string[] $seenV4Codes | ||
| * @param bool $enableOpinionated | ||
| * @return string[] | ||
| */ | ||
| protected function listUnmappedActionCodes(array $seenV4Codes, bool $enableOpinionated = false): array | ||
| { | ||
| $unmapped = []; | ||
|
|
||
| foreach ($seenV4Codes as $c) { | ||
| $m = $this->mapActionCode((string)$c, $enableOpinionated); | ||
| if ($m['enum'] === null) { | ||
| $unmapped[] = strtoupper(trim((string)$c)); | ||
| } | ||
| } | ||
|
|
||
| return array_values(array_unique($unmapped)); | ||
| } | ||
| } |