diff --git a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php index 1ecd9bc8..72fcf486 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php @@ -123,10 +123,10 @@ public function initialize(array $config): void { } /** - * Perform steps necessary to finalize the Petition. + * Perform steps necessary to hydrate the Person record as part of Petition finalization. * * @param int $id Attribute Collector ID - * @param Petition $petition + * @param \App\Model\Entity\Petition $petition * @return bool true on success * @since COmanage Registry v5.1.0 */ @@ -166,7 +166,7 @@ public function finalize(int $id, \App\Model\Entity\Petition $petition): bool })->toArray(); $personRoleAttributes = array_keys($personRoleAttributes); - // Get all the fields/values required to build the PrersonRole + // Get all the fields/values required to build the PersonRole $fieldsForPersonRole = $attributesCollection->filter(function($attr, $key) use ($personRoleAttributes) { return in_array($attr['enrollment_attribute']['attribute'], $personRoleAttributes); })->toArray(); @@ -213,7 +213,7 @@ public function finalize(int $id, \App\Model\Entity\Petition $petition): bool ); /****** PERSON ******/ - // Filter the MVEAS Attributes and keep the field name + // Keep the person attributes $personAttributes = (new Collection($supportedAttributes))->filter(function($attr, $key) { return isset($attr['model']) && $attr['model'] == 'Person'; })->toArray(); @@ -224,11 +224,38 @@ public function finalize(int $id, \App\Model\Entity\Petition $petition): bool return in_array($attr['enrollment_attribute']['attribute'], $personAttributes); })->toArray(); - if($People->saveAttributes($person->id, $fieldsForPerson) === false) { + + try { + $People->saveAttributes($person->id, $fieldsForPerson); + } catch (\Exception $e) { + $this->llog('error', __d('error', 'save', [$e->getMessage()])); $cxn->rollback(); throw new \RuntimeException(__d('error', 'save', ['Person'])); } + + /****** GROUP ******/ + // Filter the MVEAS Attributes and keep the field name + $groupAttributes = (new Collection($supportedAttributes))->filter(function($attr, $key) { + return isset($attr['model']) && $attr['model'] == 'Group'; + })->toArray(); + $groupAttributes = array_keys($groupAttributes); + + // Get all the fields/values required to build the PrersonRole + $fieldsForGroup = $attributesCollection->filter(function($attr, $key) use ($groupAttributes) { + return in_array($attr['enrollment_attribute']['attribute'], $groupAttributes); + })->toArray(); + + + try { + $groupMemberObj = TableRegistry::getTableLocator()->get('GroupMembers'); + $groupMemberObj->saveAttributes($person->id, $fieldsForGroup); + } catch (\Exception $e) { + $this->llog('error', __d('error', 'save', [$e->getMessage()])); + $cxn->rollback(); + throw new \RuntimeException(__d('error', 'save', ['GroupMembers'])); + } + // Save the Date Of Birth. This is the only one that is single valued // and goes under the Person diff --git a/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php index 5fa74858..780b8c06 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php @@ -133,12 +133,12 @@ public function initialize(array $config): void { } /** - * Perform steps necessary to finalize the Petition. - * - * @since COmanage Registry v5.1.0 + * Perform steps necessary to hydrate the Person record as part of Petition finalization. + * * @param int $id Basic Attribute Collector ID - * @param Petition $petition Petition + * @param \App\Model\Entity\Petition $petition Petition * @return bool true on success + * @since COmanage Registry v5.1.0 */ public function finalize(int $id, \App\Model\Entity\Petition $petition) { diff --git a/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php b/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php index f08d24f8..109940ca 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/EmailVerifiersTable.php @@ -280,12 +280,12 @@ public function assembleVerifiableAddresses( } /** - * Perform steps necessary to finalize the Petition. - * - * @since COmanage Registry v5.1.0 + * Perform steps necessary to hydrate the Person record as part of Petition finalization. + * * @param int $id Invitation Accepter ID - * @param Petition $petition Petition + * @param \App\Model\Entity\Petition $petition Petition * @return bool true on success + * @since COmanage Registry v5.1.0 */ public function finalize(int $id, \App\Model\Entity\Petition $petition) { diff --git a/app/plugins/CoreEnroller/src/Model/Table/IdentifierCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/IdentifierCollectorsTable.php index 6a6d285b..45253a40 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/IdentifierCollectorsTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/IdentifierCollectorsTable.php @@ -119,12 +119,12 @@ public function initialize(array $config): void { } /** - * Perform steps necessary to finalize the Petition. - * - * @since COmanage Registry v5.1.0 + * Perform steps necessary to hydrate the Person record as part of Petition finalization. + * * @param int $id Invitation Accepter ID - * @param Petition $petition Petition + * @param \App\Model\Entity\Petition $petition Petition * @return bool true on success + * @since COmanage Registry v5.1.0 */ public function finalize(int $id, \App\Model\Entity\Petition $petition) { diff --git a/app/plugins/CoreEnroller/src/Model/Table/InvitationAcceptersTable.php b/app/plugins/CoreEnroller/src/Model/Table/InvitationAcceptersTable.php index 19093ca6..b696a995 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/InvitationAcceptersTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/InvitationAcceptersTable.php @@ -112,12 +112,12 @@ public function initialize(array $config): void { } /** - * Perform steps necessary to finalize the Petition. - * - * @since COmanage Registry v5.1.0 + * Perform steps necessary to hydrate the Person record as part of Petition finalization. + * * @param int $id Invitation Accepter ID - * @param Petition $petition Petition + * @param \App\Model\Entity\Petition $petition Petition * @return bool true on success + * @since COmanage Registry v5.1.0 */ public function finalize(int $id, \App\Model\Entity\Petition $petition) { diff --git a/app/plugins/EnvSource/src/Controller/EnvSourceCollectorsController.php b/app/plugins/EnvSource/src/Controller/EnvSourceCollectorsController.php index aad58225..2383f3df 100644 --- a/app/plugins/EnvSource/src/Controller/EnvSourceCollectorsController.php +++ b/app/plugins/EnvSource/src/Controller/EnvSourceCollectorsController.php @@ -121,24 +121,6 @@ public function dispatch(string $id) { $this->render('/Standard/dispatch'); } - /** - * Display information about this Step. - * - * @since COmanage Registry v5.1.0 - * @param string $id Attribute Collector ID - */ - - public function display(string $id) { - $petition = $this->getPetition(); - - $this->set('vv_petition_env_identities', $this->EnvSourceCollectors - ->PetitionEnvIdentities - ->find() - ->where(['PetitionEnvIdentities.petition_id' => $petition->id]) - ->contain(['EnvSourceIdentities']) - ->firstOrFail()); - } - /** * Indicate whether this Controller will handle some or all authnz. * diff --git a/app/plugins/EnvSource/src/View/Cell/EnvSourceCollectorsCell.php b/app/plugins/EnvSource/src/View/Cell/EnvSourceCollectorsCell.php new file mode 100644 index 00000000..fed70617 --- /dev/null +++ b/app/plugins/EnvSource/src/View/Cell/EnvSourceCollectorsCell.php @@ -0,0 +1,85 @@ + + */ + protected $_validCellOptions = [ + 'vv_obj', + 'vv_step', + 'viewVars', + ]; + + /** + * Initialization logic run at the end of object construction. + * + * @return void + */ + public function initialize(): void + { + } + + /** + * Default display method. + * + * @param int $petitionId + * @return void + * @since COmanage Registry v5.1.0 + */ + public function display(int $petitionId): void + { + $EnvSourceCollectors = $this->fetchTable('EnvSourceCollectors'); + + $this->set('vv_petition_env_identities', $EnvSourceCollectors + ->PetitionEnvIdentities + ->find() + ->where(['PetitionEnvIdentities.petition_id' => $petitionId]) + ->contain(['EnvSourceIdentities']) + ->firstOrFail()); + + $this->set('vv_step', $this->vv_step); + $this->set('vv_obj', $this->vv_obj); + } +} diff --git a/app/plugins/EnvSource/templates/cell/EnvSourceCollectors/display.php b/app/plugins/EnvSource/templates/cell/EnvSourceCollectors/display.php new file mode 100644 index 00000000..4990a5aa --- /dev/null +++ b/app/plugins/EnvSource/templates/cell/EnvSourceCollectors/display.php @@ -0,0 +1,40 @@ +env_source_identity->env_attributes); + +?> + + \ No newline at end of file diff --git a/app/plugins/EnvSource/templates/element/petition/envSourceCollectorsStep.php b/app/plugins/EnvSource/templates/element/petition/envSourceCollectorsStep.php deleted file mode 100644 index 7f2f16ea..00000000 --- a/app/plugins/EnvSource/templates/element/petition/envSourceCollectorsStep.php +++ /dev/null @@ -1,13 +0,0 @@ -env_source_identity->env_attributes); - - // XXX this needs to be refactored -?> - - diff --git a/app/plugins/EnvSource/tests/TestCase/View/Cell/EnvSourceCollectorsCellTest.php b/app/plugins/EnvSource/tests/TestCase/View/Cell/EnvSourceCollectorsCellTest.php new file mode 100644 index 00000000..132ffc7c --- /dev/null +++ b/app/plugins/EnvSource/tests/TestCase/View/Cell/EnvSourceCollectorsCellTest.php @@ -0,0 +1,59 @@ +request = $this->getMockBuilder('Cake\Http\ServerRequest')->getMock(); + $this->response = $this->getMockBuilder('Cake\Http\Response')->getMock(); + $this->EnvSourceCollectors = new EnvSourceCollectorsCell($this->request, $this->response); + } + + /** + * tearDown method + * + * @return void + */ + protected function tearDown(): void + { + unset($this->EnvSourceCollectors); + + parent::tearDown(); + } +} diff --git a/app/src/Model/Behavior/TimezoneBehavior.php b/app/src/Model/Behavior/TimezoneBehavior.php index 6c782da6..dfa9655b 100644 --- a/app/src/Model/Behavior/TimezoneBehavior.php +++ b/app/src/Model/Behavior/TimezoneBehavior.php @@ -64,9 +64,7 @@ public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $opti if(!empty($data[$f])) { // This returns a DateTime object adjusting for localTZ $offsetDT = new \DateTime($data[$f], $this->tz); - - // strftime converts a timestamp according to server localtime (which should be UTC) - $data[$f] = strftime("%F %T", $offsetDT->getTimestamp()); + $data[$f] = date("Y-m-d H:i:s", $offsetDT->getTimestamp()); } } } diff --git a/app/src/Model/Table/AddressesTable.php b/app/src/Model/Table/AddressesTable.php index 741ef659..2042a73c 100644 --- a/app/src/Model/Table/AddressesTable.php +++ b/app/src/Model/Table/AddressesTable.php @@ -316,7 +316,6 @@ public function saveAttributes(int $personId, ?int $roleId, string $parentModel, $address['person_role_id'] = $roleId; } - // We need to get this from CoSettings?? foreach($fields as $fld) { $address[$fld->column_name] = $fld->value; } diff --git a/app/src/Model/Table/GroupMembersTable.php b/app/src/Model/Table/GroupMembersTable.php index 48d540b6..916b8343 100644 --- a/app/src/Model/Table/GroupMembersTable.php +++ b/app/src/Model/Table/GroupMembersTable.php @@ -549,4 +549,32 @@ public function validationDefault(Validator $validator): Validator { return $validator; } + + + /** + * Save attributes for a person. + * + * This method is responsible for saving attributes for a given person. + * It constructs an entity with the provided fields and ensures the entity + * is saved successfully. + * + * @param int $personId The ID of the person to save attributes for. + * @param array $fields An array of fields to update, where each field + * includes an enrollment attribute and its value. + * + * @return GroupMember The saved entity representing the person's role. + * + */ + public function saveAttributes(int $personId, array $fields): GroupMember + { + $member = [ + 'person_id' => $personId, + ]; + + foreach($fields as $fld) { + $member[$fld->enrollment_attribute->attribute] = $fld->value; + } + + return $this->saveOrFail($this->newEntity($member)); + } } \ No newline at end of file diff --git a/app/src/Model/Table/NamesTable.php b/app/src/Model/Table/NamesTable.php index 11546b87..7f636c58 100644 --- a/app/src/Model/Table/NamesTable.php +++ b/app/src/Model/Table/NamesTable.php @@ -489,13 +489,10 @@ public function saveAttributes(int $personId, ?int $roleId, string $parentModel, $name['primary_name'] = true; } - // We need to get this from CoSettings?? foreach($fields as $fld) { $name[$fld->column_name] = $fld->value; } - // XXX Check if we already have an this value saved - $this->saveOrFail($this->newEntity($name)); return true; } diff --git a/app/src/Model/Table/PeopleTable.php b/app/src/Model/Table/PeopleTable.php index 60c3d414..d35adea4 100644 --- a/app/src/Model/Table/PeopleTable.php +++ b/app/src/Model/Table/PeopleTable.php @@ -29,15 +29,16 @@ namespace App\Model\Table; +use App\Model\Entity\Person; use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; use \App\Lib\Enum\ActionEnum; use \App\Lib\Enum\GroupTypeEnum; +use \App\Lib\Enum\ProvisioningEligibilityEnum; use \App\Lib\Enum\StatusEnum; use \App\Lib\Enum\SuspendableStatusEnum; -use \App\Lib\Enum\ProvisioningEligibilityEnum; use \App\Lib\Util\PaginatedSqlIterator; class PeopleTable extends Table { @@ -368,7 +369,7 @@ public function findIndexed(Query $query): Query { * @return string Display field */ - public function generateDisplayField(\App\Model\Entity\Person $entity): string { + public function generateDisplayField(Person $entity): string { if(empty($entity->primary_name)) { throw new \InvalidArgumentException(__d('error', 'Names.primary_name')); } @@ -745,14 +746,11 @@ public function validationDefault(Validator $validator): Validator { * @param int $personId The ID of the person entity to update. * @param array $fields An array of fields to update, where each field is expected to have an * `enrollment_attribute` with an `attribute` property, and a `value` property containing the value to update. - * @return \App\Model\Entity\Person The updated person entity after saving. - * @throws \Cake\Datasource\Exception\RecordNotFoundException If the person with the given ID does not exist. - * @throws \RuntimeException If the person entity could not be saved. + * @return Person The updated person entity after saving. * @since COmanage Registry v5.1.0 */ - public function saveAttributes(int $personId, array $fields): \App\Model\Entity\Person + public function saveAttributes(int $personId, array $fields): Person { - $person = $this->get($personId); foreach ($fields as $field) { $attribute = $field->enrollment_attribute->attribute; @@ -769,6 +767,6 @@ public function saveAttributes(int $personId, array $fields): \App\Model\Entity\ $person->$attribute = $value; } - return $this->save($person); + return $this->saveOrFail($person); } } \ No newline at end of file diff --git a/app/src/Model/Table/PersonRolesTable.php b/app/src/Model/Table/PersonRolesTable.php index 548b57ac..02828302 100644 --- a/app/src/Model/Table/PersonRolesTable.php +++ b/app/src/Model/Table/PersonRolesTable.php @@ -29,10 +29,10 @@ namespace App\Model\Table; +use App\Model\Entity\PersonRole; use Cake\Event\EventInterface; use \Cake\I18n\FrozenTime; use Cake\ORM\Entity; -use Cake\ORM\Query; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; @@ -335,7 +335,7 @@ public function buildRules(RulesChecker $rules): RulesChecker { * @return string Display field */ - public function generateDisplayField(\App\Model\Entity\PersonRole $entity): string { + public function generateDisplayField(PersonRole $entity): string { // Try to find something renderable if(!empty($entity->title)) { @@ -717,23 +717,31 @@ public function validationDefault(Validator $validator): Validator { * @param int $personId ID of the person for whom attributes are being saved * @param array $fields Array of fields/attributes to be saved * - * @return \App\Model\Entity\PersonRole The newly saved Role + * @return PersonRole The newly saved Role * @throws \Cake\Datasource\Exception\RecordNotFoundException If an issue occurs during saving * @since COmanage Registry v5.1.0 */ - public function saveAttributes(int $personId, array $fields): \App\Model\Entity\PersonRole + public function saveAttributes(int $personId, array $fields): PersonRole { + $dateFormat = 'yyyy-MM-dd HH:mm:ss'; + $role = [ 'person_id' => $personId, ]; - // We need to get this from CoSettings?? foreach($fields as $fld) { - $role[$fld->enrollment_attribute->attribute] = $fld->value; + $attribute = $fld->enrollment_attribute->attribute; + $value = $fld->value; + if( + ($attribute === 'valid_from' || $attribute === 'valid_through') + && is_string($value) + ) { + $dob = FrozenTime::parse($value); + $value = $dob->i18nFormat($dateFormat); + } + $role[$attribute] = $value; } - // XXX Check if we already have one - return $this->saveOrFail($this->newEntity($role)); } } \ No newline at end of file diff --git a/app/src/Model/Table/TelephoneNumbersTable.php b/app/src/Model/Table/TelephoneNumbersTable.php index 72a938f5..00073179 100644 --- a/app/src/Model/Table/TelephoneNumbersTable.php +++ b/app/src/Model/Table/TelephoneNumbersTable.php @@ -254,7 +254,6 @@ public function saveAttributes(int $personId, ?int $roleId, string $parentModel, $telephone['person_role_id'] = $roleId; } - // We need to get this from CoSettings?? foreach($fields as $fld) { $telephone[$fld->column_name] = $fld->value; } diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php index 34ca57ce..b022abca 100644 --- a/app/src/View/Helper/FieldHelper.php +++ b/app/src/View/Helper/FieldHelper.php @@ -315,25 +315,6 @@ public function dateField(string $fieldName, // that will interact with the field value. Allowing direct access to the input field is for // accessibility purposes. - // ACTION VIEW or Readonly Field - // The latter applies for the attribute collection view - if($this->action == 'view' - || - (isset($fieldArgs['readonly']) && $fieldArgs['readonly']) - ) { - // return the date as plaintext - $element = $this->getView()->element('form/notSetDiv', [], [ - 'cache' => '_html_elements', - ]); - if ($date_object !== null) { - // Adjust the time back to the user's timezone - $element = ''; - } - - // Return this to the generic control() function - return $element; - } - // Special-case the very common "valid_from" and "valid_through" fields, so we won't need // to specify their types in fields.inc. $pickerTypeName = $fieldArgs['fieldNameAlias'] ?? $fieldName; @@ -363,6 +344,28 @@ public function dateField(string $fieldName, $pickerDate = $date_object->i18nFormat($dateFormat); } + // ACTION VIEW or Readonly Field + // The latter applies for the attribute collection view + // For the Attribute Collection View we also need a hidden field + if($this->action == 'view' + || + (isset($fieldArgs['readonly']) && $fieldArgs['readonly']) + ) { + // return the date as plaintext + // Add a hidden field + $element = $this->getView()->element('form/notSetDiv', [], [ + 'cache' => '_html_elements', + ]); + if ($date_object !== null) { + // Adjust the time back to the user's timezone + $element = $this->Form->hidden($fieldName, $coptions) + . ''; + } + + // Return this to the generic control() function + return $element; + } + // Set the date picker floor year value (-100 years)() $pickerDateFT = new FrozenTime($pickerDate); $pickerDateFT = $pickerDateFT->subYears(100);