diff --git a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php index 1ecd9bc8..bf8ab7e7 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php @@ -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/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..7f01f6d9 100644 --- a/app/src/Model/Table/GroupMembersTable.php +++ b/app/src/Model/Table/GroupMembersTable.php @@ -549,4 +549,33 @@ 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, + ]; + + // We need to get this from CoSettings?? + 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..2aa2b2e5 100644 --- a/app/src/Model/Table/NamesTable.php +++ b/app/src/Model/Table/NamesTable.php @@ -494,8 +494,6 @@ public function saveAttributes(int $personId, ?int $roleId, string $parentModel, $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..2a292a71 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,32 @@ 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..33966e3f 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,27 @@ 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 = ''; + } + + // Return this to the generic control() function + return $this->Form->hidden($fieldName, $coptions) . $element; + } + // Set the date picker floor year value (-100 years)() $pickerDateFT = new FrozenTime($pickerDate); $pickerDateFT = $pickerDateFT->subYears(100);