diff --git a/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php b/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php
index 27faa274..7e1631bd 100644
--- a/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php
+++ b/app/plugins/CoreEnroller/src/Controller/AttributeCollectorsController.php
@@ -30,9 +30,9 @@
namespace CoreEnroller\Controller;
use App\Controller\StandardEnrollerController;
-use App\Lib\Enum\PetitionStatusEnum;
use Cake\Event\EventInterface;
use Cake\Http\Response;
+use Cake\ORM\TableRegistry;
class AttributeCollectorsController extends StandardEnrollerController {
public $paginate = [
@@ -121,16 +121,4 @@ public function dispatch(string $id) {
$this->render('/Standard/dispatch');
}
-
- /**
- * Display information about this Step.
- *
- * @since COmanage Registry v5.0.0
- * @param string $id Attribute Collector ID
- */
-
- public function display(string $id) {
- debug("display something for this petition");
- debug($this->getPetition());
- }
}
diff --git a/app/plugins/CoreEnroller/src/Controller/BasicAttributeCollectorsController.php b/app/plugins/CoreEnroller/src/Controller/BasicAttributeCollectorsController.php
index bf3f701f..01890e70 100644
--- a/app/plugins/CoreEnroller/src/Controller/BasicAttributeCollectorsController.php
+++ b/app/plugins/CoreEnroller/src/Controller/BasicAttributeCollectorsController.php
@@ -87,21 +87,4 @@ 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_basic_attribute_set', $this->BasicAttributeCollectors
- ->PetitionBasicAttributeSets
- ->find()
- ->where(['PetitionBasicAttributeSets.petition_id' => $petition->id])
- ->firstOrFail());
- }
}
diff --git a/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php b/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php
index c79f21e4..35595ccd 100644
--- a/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php
+++ b/app/plugins/CoreEnroller/src/Controller/EmailVerifiersController.php
@@ -216,25 +216,4 @@ public function dispatch(string $id) {
$this->render('/Standard/dispatch');
}
-
- /**
- * Display information about this Step.
- *
- * @since COmanage Registry v5.1.0
- * @param string $id Email Verifiers ID
- */
-
- public function display(string $id) {
- $petition = $this->getPetition();
-
- $PetitionVerifications = TableRegistry::getTableLocator()->get('CoreEnroller.PetitionVerifications');
-
- // Because Petition Verifications are not tracked on a per-step basis, we just pull all
- // associated with the Petition
-
- $this->set('vv_pv', $PetitionVerifications->find()
- ->where(['PetitionVerifications.petition_id' => $petition->id])
- ->contain(['Verifications'])
- ->all());
- }
}
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/src/Controller/IdentifierCollectorsController.php b/app/plugins/CoreEnroller/src/Controller/IdentifierCollectorsController.php
index 9b0fe090..be0e63cf 100644
--- a/app/plugins/CoreEnroller/src/Controller/IdentifierCollectorsController.php
+++ b/app/plugins/CoreEnroller/src/Controller/IdentifierCollectorsController.php
@@ -96,21 +96,6 @@ public function dispatch(string $id) {
}
}
- /**
- * Display information about this Step.
- *
- * @since COmanage Registry v5.1.0
- * @param string $id Invitation Accepters ID
- */
-
- public function display(string $id) {
- $petition = $this->getPetition();
-
- $PetitionIdentifiers = TableRegistry::getTableLocator()->get('CoreEnroller.PetitionIdentifiers');
-
- $this->set('vv_pi', $PetitionIdentifiers->find()->where(['petition_id' => $petition->id])->first());
- }
-
/**
* Indicate whether this Controller will handle some or all authnz.
*
diff --git a/app/plugins/CoreEnroller/src/Controller/InvitationAcceptersController.php b/app/plugins/CoreEnroller/src/Controller/InvitationAcceptersController.php
index d6b91802..90d05ba7 100644
--- a/app/plugins/CoreEnroller/src/Controller/InvitationAcceptersController.php
+++ b/app/plugins/CoreEnroller/src/Controller/InvitationAcceptersController.php
@@ -133,19 +133,4 @@ public function dispatch(string $id) {
$this->render('/Standard/dispatch');
}
-
- /**
- * Display information about this Step.
- *
- * @since COmanage Registry v5.1.0
- * @param string $id Invitation Accepters ID
- */
-
- public function display(string $id) {
- $petition = $this->getPetition();
-
- $PetitionAcceptances = TableRegistry::getTableLocator()->get('CoreEnroller.PetitionAcceptances');
-
- $this->set('vv_pa', $PetitionAcceptances->find()->where(['petition_id' => $petition->id])->first());
- }
}
diff --git a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php
index 18e3c22e..03ecee81 100644
--- a/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php
+++ b/app/plugins/CoreEnroller/src/Model/Table/AttributeCollectorsTable.php
@@ -29,6 +29,7 @@
namespace CoreEnroller\Model\Table;
+use App\Model\Entity\Petition;
use Cake\Datasource\ConnectionManager;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
@@ -117,21 +118,32 @@ public function initialize(array $config): void {
/**
* Perform steps necessary to finalize the Petition.
- *
- * @since COmanage Registry v5.0.0
- * @param int $id Attribute Collector ID
- * @param int $petitionId Petition ID
+ *
+ * @param int $id Attribute Collector ID
+ * @param Petition $petition
* @return bool true on success
+ * @since COmanage Registry v5.1.0
*/
- public function finalize(int $id, int $petitionId) {
-// XXX convert Petition Attributes to operational Attributes
-// keep in mind this can be called multiple times if the plugin is
-// instantiated more than once in the Enrollment Flow ($id will be different)
-// any errors should be logged or otherwise managed, returning false
-// or throwing an error will NOT prevent the petition from finalizing
+ public function finalize(int $id, \App\Model\Entity\Petition $petition) {
+ $cfg = $this->get($id);
+
+ if(empty($petition->enrollee_person_id)) {
+ throw new \InvalidArgumentException(__d('error', 'Petitions.enrollee.notfound', [$petition->id]));
+ }
+
+ $People = TableRegistry::getTableLocator()->get('People');
+
+ $person = $People->get($petition->enrollee_person_id);
-debug("in AttributeCollector finalize");
+ $attributes = $this->EnrollmentAttributes
+ ->PetitionAttributes
+ ->find()
+ ->where(['petition_id' => $petition->id])
+ ->firstOrFail();
+
+ // XXX Should i save the primary name?
+ // XXX Should i save the email?
return true;
}
@@ -166,15 +178,33 @@ public function upsert(int $id, int $petitionId, array $attributes) {
foreach($attributes as $enrollmentAttributeLabel => $value) {
// Remove field- prefix from the form field name
- $enrollmentAttributeId = (int)substr($enrollmentAttributeLabel, 6);
+ $fieldToParts = explode('-', $enrollmentAttributeLabel);
+ // MVAs have multiple columns. For example a name has:
+ // given, surname, prefix, ...
+ $columnName = null;
+ if (count($fieldToParts) > 2) {
+ // There is a type ID in the middle
+ $columnName = $fieldToParts[1];
+ }
+ // The enrollment Attribute ID is the last part
+ $enrollmentAttributeId = (int)array_pop($fieldToParts);
+
+ // The people picker will send a complex string and not just the id. We need to extract it ourselves.
+ $re = '/^.*\(ID: (\d+)\)$/m';
+ preg_match_all($re, $value, $matches, PREG_SET_ORDER, 0);
+ if(!empty($matches)) {
+ $value = $matches[0][1];
+ }
$newAttribute = [
'petition_id' => $petitionId,
'enrollment_attribute_id' => $enrollmentAttributeId,
- 'value' => $value
+ 'value' => $value,
+ // This is the column name for the attributes that consist of multiple fields, like the name or the address
+ 'column_name' => $columnName,
];
- if(array_key_exists($enrollmentAttributeId, $currentAttributes)) {
+ if(\array_key_exists($enrollmentAttributeId, $currentAttributes)) {
// This is an update of an existing attribute
$newAttribute['id'] = $currentAttributes[$enrollmentAttributeId];
diff --git a/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php
index cd0ac076..5fa74858 100644
--- a/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php
+++ b/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php
@@ -147,7 +147,7 @@ public function finalize(int $id, \App\Model\Entity\Petition $petition) {
// At this point there is a Person record allocated and stored in the Petition,
// but it doesn't have any attributes on it, including a Primary Name.
// We assume we're the only attribute collector, so we'll force a Primary Name
- // based on the Basic Attribtues, and create a skeletal role.
+ // based on the Basic Attributes, and create a skeletal role.
if(empty($petition->enrollee_person_id)) {
throw new \InvalidArgumentException(__d('error', 'Petitions.enrollee.notfound', [$petition->id]));
diff --git a/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php b/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php
index 161d873e..d26329d5 100644
--- a/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php
+++ b/app/plugins/CoreEnroller/src/Model/Table/PetitionAttributesTable.php
@@ -103,6 +103,7 @@ public function validationDefault(Validator $validator): Validator {
$validator->notEmptyString('enrollment_attribute_id');
$this->registerStringValidation($validator, $schema, 'value', false);
+ $this->registerStringValidation($validator, $schema, 'column', false);
return $validator;
}
diff --git a/app/plugins/CoreEnroller/src/config/plugin.json b/app/plugins/CoreEnroller/src/config/plugin.json
index dbb666b8..bb58ddb5 100644
--- a/app/plugins/CoreEnroller/src/config/plugin.json
+++ b/app/plugins/CoreEnroller/src/config/plugin.json
@@ -111,7 +111,8 @@
"id": {},
"petition_id": {},
"enrollment_attribute_id": { "type": "integer", "foreignkey": { "table": "enrollment_attributes", "column": "id" } },
- "value": { "type": "string", "size": 160 }
+ "value": { "type": "string", "size": 160 },
+ "column_name": { "notnull": false, "type": "string", "size": 64 }
},
"indexes": {
"petition_attributes_i1": { "columns": [ "petition_id" ] },
diff --git a/app/plugins/CoreEnroller/templates/BasicAttributeCollectors/display.php b/app/plugins/CoreEnroller/templates/BasicAttributeCollectors/display.php
deleted file mode 100644
index 4247e740..00000000
--- a/app/plugins/CoreEnroller/templates/BasicAttributeCollectors/display.php
+++ /dev/null
@@ -1,8 +0,0 @@
-
- - Honorific: = $vv_petition_basic_attribute_set['honorific'] ?? "" ?>
- - Given: = $vv_petition_basic_attribute_set['given'] ?? "" ?>
- - Middle: = $vv_petition_basic_attribute_set['middle'] ?? "" ?>
- - Family: = $vv_petition_basic_attribute_set['family'] ?? "" ?>
- - Suffix: = $vv_petition_basic_attribute_set['suffix'] ?? "" ?>
- - Email: = $vv_petition_basic_attribute_set['mail'] ?? "" ?>
-
diff --git a/app/plugins/CoreEnroller/templates/EmailVerifiers/display.php b/app/plugins/CoreEnroller/templates/EmailVerifiers/display.php
deleted file mode 100644
index a3aded80..00000000
--- a/app/plugins/CoreEnroller/templates/EmailVerifiers/display.php
+++ /dev/null
@@ -1,24 +0,0 @@
-\n";
-
- foreach($vv_pv as $pv) {
- print "" . $pv->mail . ": ";
-
- if(!empty($pv->verification) && $pv->verification->isVerified()) {
- print __d('result', 'Verifications.status', [
- VerificationMethodEnum::getLocalization($pv->verification->method),
- $this->Time->nice($pv->verification->verification_time, $vv_tz)
- ]);
- } else {
- print __d('field', 'unverified');
- }
-
- print "";
- }
-
- print "\n";
-}
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/columns.inc b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/columns.inc
index 26fcceba..2a4a83c3 100644
--- a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/columns.inc
+++ b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/columns.inc
@@ -49,6 +49,10 @@ $indexColumns = [
'required' => [
'type' => 'boolean',
'class' => 'YesBooleanEnum'
+ ],
+ 'hidden' => [
+ 'type' => 'boolean',
+ 'class' => 'YesBooleanEnum'
]
];
diff --git a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
index 0ea015f2..09a3a971 100644
--- a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
+++ b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
@@ -32,8 +32,7 @@ use \Cake\Utility\Inflector;
$attribute_type = null;
if($vv_action == 'add') {
$attribute_type = $this->request->getQuery('attribute_type');
-} else if($vv_action == 'edit' && !empty($vv_obj)
-) {
+} else if($vv_action == 'edit' && !empty($vv_obj)) {
$attribute_type = $vv_obj->attribute;
}
diff --git a/app/plugins/CoreEnroller/templates/IdentifierCollectors/display.php b/app/plugins/CoreEnroller/templates/IdentifierCollectors/display.php
deleted file mode 100644
index 30359a60..00000000
--- a/app/plugins/CoreEnroller/templates/IdentifierCollectors/display.php
+++ /dev/null
@@ -1,4 +0,0 @@
-identifier)) {
- print __d('core_enroller', 'result.IdentifierCollector.collected', [$vv_pi->identifier]);
-}
diff --git a/app/plugins/CoreEnroller/templates/element/field.php b/app/plugins/CoreEnroller/templates/element/field.php
index b5cd48d5..80a3b8cd 100644
--- a/app/plugins/CoreEnroller/templates/element/field.php
+++ b/app/plugins/CoreEnroller/templates/element/field.php
@@ -119,5 +119,5 @@
'formArguments' => $formArguments
]),
// Default use case
- default => $this->element('form/listItem', ['arguments' => $formArguments])
+ default => $this->Field->getElementsForDisabledInput('form/listItem', $formArguments)
};
diff --git a/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
index 58c89298..e8e7e53e 100644
--- a/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
+++ b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
@@ -38,12 +38,41 @@
$isRequiredFromValidationRule = false;
$supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
+// Field Options array
+$options = [];
+
if(isset($supportedAttributes['mveaModel'])) {
$supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
$modelTable = $this->Petition->getTable($supportedAttributes['mveaModel']);
$isRequiredFromValidationRule = !$modelTable->getValidator()->field($field)->isEmptyAllowed();
}
+// Do we have a default value configured?
+// Either a value or an Environmental Variable,
+// Each default value is mutually exclusive to the rest. We do not have to worry about a conflict.
+$options['default'] = match(true) {
+ isset($attr->default_value) => $attr->default_value,
+ // XXX The $attr->default_value_env_name for the name attribute is tricky. Since the name has many values.
+ // Check the EnvSource plugin
+ isset($attr->default_value_env_name)
+ && getenv($attr->default_value_env_name) !== false => getenv($attr->default_value_env_name),
+ isset($attr->default_value_datetime) => $attr->default_value_datetime,
+ default => ''
+};
+
+// If we are re-rendering the Petition, override the default value with whatever
+// was previously saved
+if(!empty($vv_petition_attributes)) {
+ $curEntity = $vv_petition_attributes->firstMatch([
+ 'enrollment_attribute_id' => $attr->id,
+ 'column_name' => $field
+ ]);
+
+ if(!empty($curEntity->value)) {
+ $options['default'] = $curEntity->value;
+ }
+}
+
// Construct the field arguments
$formArguments = [
// We prefix the attribute ID with a string because Cake seems to sometimes have
@@ -53,6 +82,9 @@
'fieldType' => $modelTable->getSchema()->getColumn($field)['type'],
'fieldNameAlias' => $attr->attribute // the field name to its enrollment attribute field name
];
+
+// Set the final fieldOptions
+$formArguments['fieldOptions'] = $options;
?>
">
diff --git a/app/plugins/CoreEnroller/templates/element/petition/attributeCollectorsStep.php b/app/plugins/CoreEnroller/templates/element/petition/attributeCollectorsStep.php
new file mode 100644
index 00000000..0293a519
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/petition/attributeCollectorsStep.php
@@ -0,0 +1,92 @@
+petition_attributes, '{n}.enrollment_attribute_id');
+$vv_enrollment_atttributes_ids = array_unique($vv_enrollment_atttributes_ids);
+
+$enrollmentAttributesTable = $this->Petition->getTable('EnrollmentAttributes');
+$vv_enrollment_attributes = $enrollmentAttributesTable->find()
+ ->where(fn(QueryExpression $exp, Query $q) => $exp->in('id', $vv_enrollment_atttributes_ids))
+ ->order(['ordr' => 'ASC'])
+ ->toArray();
+
+?>
+
+
+
+ petition_attributes)->filter(fn($attr) => $attr->enrollment_attribute_id === $attribute->id) ?>
+ count() === 1): ?>
+ first();
+ $value = $attr->value ?? 'N/A';
+ if(!empty($value) && str_ends_with($attribute->attribute, 'person_id')) {
+ // We need to load the associated model data
+ $associatedModel = $this->Petition->getRecordForId('person_id', $attr->value, ['PrimaryName']);
+ $value = $associatedModel['primary_name']['given'] . ' '
+ . $associatedModel['primary_name']['family'] . ' '
+ . '(ID: ' . $associatedModel['id'] . ')';
+ $value = $this->Html->link($value,
+ ['controller' => 'people', 'action' => 'edit', $attr->value]);
+ } elseif(!empty($value) && str_ends_with($attribute->attribute, '_id')) {
+ // We need to load the associated model data
+ $associatedModel = $this->Petition->getRecordForId($attribute->attribute, $attr->value);
+ $value = $associatedModel['name'] ?? $associatedModel['value'] ?? $associatedModel['description'] ?? 'N/A';
+ $value = $this->Html->link($value,
+ ['controller' => \App\Lib\Util\StringUtilities::foreignKeyToController($attribute->attribute), 'action' => 'edit', $attr->value]);
+ }
+ ?>
+ -
+
= $attribute->label ?>
+ = $value ?>
+
+
+
+ -
+
= $attribute->label ?>
+
+
+ -
+
= $attr->column_name ?>
+ = $attr->value ?>
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreEnroller/templates/element/petition/basicAttributeCollectorsStep.php b/app/plugins/CoreEnroller/templates/element/petition/basicAttributeCollectorsStep.php
new file mode 100644
index 00000000..e56d9dfd
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/petition/basicAttributeCollectorsStep.php
@@ -0,0 +1,69 @@
+id === null) {
+ return __d('error', 'notfound', 'Petition Attributes');
+ }
+
+ $tableObj = $this->Petition->getTable('PetitionBasicAttributeSets');
+ $vv_petition_basic_attribute_set = $tableObj->find()
+ ->where(['PetitionBasicAttributeSets.petition_id' => $vv_obj->id])
+ ->firstOrFail();
+?>
+
diff --git a/app/plugins/CoreEnroller/templates/element/petition/emailVerifiersStep.php b/app/plugins/CoreEnroller/templates/element/petition/emailVerifiersStep.php
new file mode 100644
index 00000000..8e1aec59
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/petition/emailVerifiersStep.php
@@ -0,0 +1,32 @@
+Petition->getTable('CoreEnroller.PetitionVerifications');
+
+// Because Petition Verifications are not tracked on a per-step basis, we just pull all
+// associated with the Petition
+
+$vv_pv = $PetitionVerifications->find()
+ ->where(['PetitionVerifications.petition_id' => $vv_obj->id])
+ ->contain(['Verifications'])
+ ->all();
+
+?>
+
+
+
+
+ - = $pv->mail ?>:
+ verification) && $pv->verification->isVerified()): ?>
+ = __d('result', 'Verifications.status', [
+ VerificationMethodEnum::getLocalization($pv->verification->method),
+ $this->Time->nice($pv->verification->verification_time, $vv_tz)
+ ]) ?>
+
+ = __d('field','unverified') ?>?>
+
+
+
+
+
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/templates/element/petition/identifierCollectorsStep.php b/app/plugins/CoreEnroller/templates/element/petition/identifierCollectorsStep.php
new file mode 100644
index 00000000..f486c6e1
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/petition/identifierCollectorsStep.php
@@ -0,0 +1,8 @@
+Petition->getTable('CoreEnroller.PetitionIdentifiers');
+
+$vv_pi = $PetitionIdentifiers->find()->where(['petition_id' => $vv_obj->id])->first();
+
+if(!empty($vv_pi->identifier)) {
+ print __d('core_enroller', 'result.IdentifierCollector.collected', [$vv_pi->identifier]);
+}
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/templates/InvitationAccepters/display.php b/app/plugins/CoreEnroller/templates/element/petition/invitationAcceptersStep.php
similarity index 65%
rename from app/plugins/CoreEnroller/templates/InvitationAccepters/display.php
rename to app/plugins/CoreEnroller/templates/element/petition/invitationAcceptersStep.php
index d1d91110..08ca2582 100644
--- a/app/plugins/CoreEnroller/templates/InvitationAccepters/display.php
+++ b/app/plugins/CoreEnroller/templates/element/petition/invitationAcceptersStep.php
@@ -1,4 +1,8 @@
Petition->getTable('CoreEnroller.PetitionAcceptances');
+
+$vv_pa = $PetitionAcceptances->find()->where(['petition_id' => $vv_obj->id])->first();
+
if(!empty($vv_pa)) {
if($vv_pa['accepted']) {
print __d('core_enroller', 'result.InvitationAccepters.accepted', [$vv_pa['modified']]);
diff --git a/app/src/Controller/MVEAController.php b/app/src/Controller/MVEAController.php
index 52fb641c..4a7ec650 100644
--- a/app/src/Controller/MVEAController.php
+++ b/app/src/Controller/MVEAController.php
@@ -100,7 +100,7 @@ public function beforeFilter(\Cake\Event\EventInterface $event) {
$personName = $Names->primaryName($externalIdentity->person_id);
$this->set('vv_person_name', $personName);
$this->set('vv_supertitle', $personName->full_name);
- $this->set('vv_person_id', $externalIdentity->person_id);
+ $this->set('vv_mvea_person_id', $externalIdentity->person_id);
break;
case 'person_role_id':
$PersonRoles = $this->getTableLocator()->get('PersonRoles');
@@ -113,13 +113,13 @@ public function beforeFilter(\Cake\Event\EventInterface $event) {
$personName = $Names->primaryName($roleEntity->person_id);
$this->set('vv_person_name', $personName);
$this->set('vv_supertitle', $personName->full_name);
- $this->set('vv_person_id', $roleEntity->person_id);
+ $this->set('vv_mvea_person_id', $roleEntity->person_id);
break;
case 'person_id':
$personName = $Names->primaryName((int)$primaryLink->value);
$this->set('vv_person_name', $personName);
$this->set('vv_supertitle', $personName->full_name);
- $this->set('vv_person_id', $primaryLink->value);
+ $this->set('vv_mvea_person_id', $primaryLink->value);
break;
default;
break;
diff --git a/app/src/Model/Table/PetitionsTable.php b/app/src/Model/Table/PetitionsTable.php
index fd760387..065ab20e 100644
--- a/app/src/Model/Table/PetitionsTable.php
+++ b/app/src/Model/Table/PetitionsTable.php
@@ -90,6 +90,9 @@ public function initialize(array $config): void {
$this->hasMany('PetitionStepResults')
->setDependent(true)
->setCascadeCallbacks(true);
+ $this->hasMany('CoreEnroller.PetitionAttributes')
+ ->setDependent(true)
+ ->setCascadeCallbacks(true);
$this->hasOne('Verifications')
->setDependent(true)
@@ -116,7 +119,8 @@ public function initialize(array $config): void {
'EnrolleePeople' => ['PrimaryName' => ['foreignKey' => 'person_id']],
'PetitionerPeople' => ['PrimaryName' => ['foreignKey' => 'person_id']],
'PetitionHistoryRecords',
- 'PetitionStepResults'
+ 'PetitionStepResults',
+ 'PetitionAttributes',
]);
$this->setAutoViewVars([
diff --git a/app/src/View/Helper/FieldHelper.php b/app/src/View/Helper/FieldHelper.php
index 4a221150..34ca57ce 100644
--- a/app/src/View/Helper/FieldHelper.php
+++ b/app/src/View/Helper/FieldHelper.php
@@ -304,7 +304,7 @@ public function dateField(string $fieldName,
isset($fieldArgs['default']) && is_string($fieldArgs['default']) => FrozenTime::parse($fieldArgs['default']),
// Petition View/ Value saved a FronzenTime
isset($fieldArgs['default'])
- && is_a($fieldArgs['default'], 'Cake\I18n\FrozenTime') => $fieldArgs['default'],
+ && is_a($fieldArgs['default'], 'Cake\I18n\FrozenTime') => $fieldArgs['default'],
// Table record/ Retrieve it from the Entity object
default => $this->getEntity()?->$fieldName,
};
diff --git a/app/src/View/Helper/PetitionHelper.php b/app/src/View/Helper/PetitionHelper.php
index 0f1ddec5..be426a30 100644
--- a/app/src/View/Helper/PetitionHelper.php
+++ b/app/src/View/Helper/PetitionHelper.php
@@ -35,6 +35,7 @@
use Cake\Utility\Inflector;
use Cake\View\Helper;
use CoreEnroller\Model\Table\EnrollmentAttributesTable;
+use DOMDocument;
class PetitionHelper extends Helper
{
@@ -82,7 +83,7 @@ public function populateAutoViewVars(): void
}
/**
- * Get the table validation rules
+ * Get reference to the Table Object
*
* @param string $tableName
*
diff --git a/app/src/View/Helper/TabHelper.php b/app/src/View/Helper/TabHelper.php
index 9bc78da5..71f31429 100644
--- a/app/src/View/Helper/TabHelper.php
+++ b/app/src/View/Helper/TabHelper.php
@@ -63,6 +63,8 @@ class TabHelper extends Helper
public function constructLinkUrl(string $tab, string|int $curId, bool $isNested = false): array
{
$curController = $this->getView()->getRequest()->getParam('controller');
+ $vv_associated_ids = $this->getView()->get('vv_associated_ids');
+
$modelName = $tab;
$controller = $modelName;
$plugin = null;
@@ -100,7 +102,15 @@ public function constructLinkUrl(string $tab, string|int $curId, bool $isNested
];
if ($action === 'index') {
+ $deepId = $this->getDeepNestedId($linkFilter);
+ If($deepId !== null) {
+ $linkFilterForeignKey = array_key_first($linkFilter);
+ $linkFilter[$linkFilterForeignKey] = $deepId;
+ }
$url['?'] = $linkFilter;
+ } else if ($action === 'edit') {
+ // I will get the id from the associated ids table
+ $url[] = $vv_associated_ids[$controller];
} else {
$url[] = $curId;
}
@@ -108,6 +118,49 @@ public function constructLinkUrl(string $tab, string|int $curId, bool $isNested
return $url;
}
+
+ /**
+ * Retrieve the ID for a deeply nested association.
+ *
+ * @param array $linkFilter The link filter containing foreign key details.
+ *
+ * @return int|null The ID of the deeply nested associated model or null if not found.
+ * @since COmanage Registry v5.1.0
+ */
+ public function getDeepNestedId(array $linkFilter): ?int
+ {
+ $vv_associated_ids = $this->getView()->get('vv_associated_ids');
+
+ // Get the foreign from the linkFilter
+ $linkFilterForeignKey = array_key_first($linkFilter);
+ // Generate the ModelName and instantiate the linked Table
+ $modelName = StringUtilities::foreignKeyToClassName($linkFilterForeignKey);
+ $table = TableRegistry::getTableLocator()->get($modelName);
+ $linkFilterId = $vv_associated_ids[Inflector::pluralize($modelName)] ?? null;
+ if($linkFilterId !== null) {
+ return (int)$linkFilterId;
+ }
+ $foreignKeyId = -1;
+ $foreignKey = null;
+ // This means that we are working on deep nested associations and we need
+ // to fetch more data
+ $linkFilterSchema = $table->getSchema();
+ foreach($linkFilterSchema->columns() as $column) {
+ // Check the foreign keys
+ if(str_ends_with($column, '_id')) {
+ $foreignKeytToTableName = Inflector::pluralize(StringUtilities::foreignKeyToClassName($column));
+ if(isset($vv_associated_ids[$foreignKeytToTableName])) {
+ $foreignKeyId = $vv_associated_ids[$foreignKeytToTableName];
+ $foreignKey = $column;
+ break;
+ }
+ }
+ }
+ $id = $table->find()->where([$foreignKey => $foreignKeyId])->first()->id;
+
+ return(int)$id;
+ }
+
/**
* Calculate the link Class
*
@@ -205,6 +258,7 @@ public function getCurrentId(string $tabName = null, bool $isNested = false): in
TableUtilities::treeTraversalFromId($curController, (int)$tid, $results);
}
+ $this->getView()->set('vv_associated_ids', $results);
$tabAction = $this->getTabAction($tabName, $isNested);
if(
diff --git a/app/templates/Petitions/fields.inc b/app/templates/Petitions/fields.inc
index 1665c168..5b488673 100644
--- a/app/templates/Petitions/fields.inc
+++ b/app/templates/Petitions/fields.inc
@@ -230,35 +230,40 @@ if (!empty($vv_obj?->petitioner_person?->id)) {
-
enrollment_flow->enrollment_flow_steps as $step): ?>
- petition_step_results, "{n}[enrollment_flow_step_id=$step->id]");
-
- if(!empty($result)) {
- $resultLink = [
- 'controller' => 'petitions',
- 'action' => 'result',
- $vv_obj->id,
- '?' => [
- 'enrollment_flow_step_id' => $step->id
- ]
- ];
- }
- ?>
-
+ petition_step_results, "{n}[enrollment_flow_step_id=$step->id]"); ?>
- = $step->description ?>
+ = $step->description ?>
- = !empty($result) ? $this->Html->link($result[0]->comment, $resultLink) : "" ?>
+ = !empty($result) ? $result[0]->comment : '' ?>
+
+
+ arrow_drop_down
+
+
+
+ = $step->plugin ?>
+ plugin);
+ $elementName = lcfirst($pluginClass) . 'Step';
+
+ print $this->element("$pluginName.petition/$elementName", ['vv_step' => $step]);
+ ?>
+
diff --git a/app/templates/element/subnavigation.php b/app/templates/element/subnavigation.php
index 138d38e3..cd453a96 100644
--- a/app/templates/element/subnavigation.php
+++ b/app/templates/element/subnavigation.php
@@ -42,9 +42,9 @@
$curId = $this->request->getQuery($vv_primary_link);
$linkFilter = [$vv_primary_link => $curId];
// For top-level nav
- if(!empty($vv_person_id)) {
- $curId = $vv_person_id;
- $linkFilter = ['person_id' => $vv_person_id];
+ if(!empty($vv_mvea_person_id)) {
+ $curId = $vv_mvea_person_id;
+ $linkFilter = ['person_id' => $vv_mvea_person_id];
}
} elseif (!empty($vv_obj)) {
// This will work for most top-level edit views
@@ -55,8 +55,8 @@
// these have been explicitly set in the $subnav array in fields-nav.inc, so just use them.
$curId = $tabsId;
$navController = $tabsController;
- } elseif(!empty($vv_person_id)) {
- $curId = $vv_person_id;
+ } elseif(!empty($vv_mvea_person_id)) {
+ $curId = $vv_mvea_person_id;
} elseif(
($active == 'plugin' || (!empty($vv_primary_link) && $vv_primary_link == 'enrollment_flow_id'))
&& !empty($vv_primary_link_obj)
diff --git a/app/templates/element/subnavigation/statusBadge.php b/app/templates/element/subnavigation/statusBadge.php
index 16a0ae5a..1cd6f6cb 100644
--- a/app/templates/element/subnavigation/statusBadge.php
+++ b/app/templates/element/subnavigation/statusBadge.php
@@ -35,7 +35,7 @@
return;
}
-$personId = $vv_person_id
+$personId = $vv_mvea_person_id
?? $this->request->getQuery('person_id')
?? $vv_obj?->person_id
?? $vv_obj?->id;
diff --git a/app/templates/element/subnavigation/supertitle.php b/app/templates/element/subnavigation/supertitle.php
index b5f238df..c7354fa4 100644
--- a/app/templates/element/subnavigation/supertitle.php
+++ b/app/templates/element/subnavigation/supertitle.php
@@ -38,7 +38,7 @@
* Person with deep nested dependency
*/
-$person_id = (int)($vv_person_id ?? $vv_obj?->person_id ?? $this->getRequest()->getQuery('person_id'));
+$person_id = (int)($vv_mvea_person_id ?? $vv_obj?->person_id ?? $this->getRequest()->getQuery('person_id'));
if ($person_id) {
$personFullName = $this->Tab->getPersonPrimaryName($person_id);
}
@@ -65,16 +65,22 @@
&& $vv_subnavigation_tabs[0] !== StringUtilities::entityToClassName($vv_bc_parent_obj)
) {
$object = $vv_obj ?? $$objectName?->first();
- // If we get here, it means that neither the request object nor its parent can give us a supertitle.
- // We need to fetch all the ids and get the supertitle from the root tab/node
- $results = [];
- TableUtilities::treeTraversalFromId(StringUtilities::entityToClassName($object), (int)$object->id, $results);
- $superTitleModelReference = $this->Tab->getModelTableReference($vv_subnavigation_tabs[0]);
- $superTitleModelDisplayField = $superTitleModelReference->getDisplayField();
- $superTitleModelId = $results[$vv_subnavigation_tabs[0]];
+ if ($object === null) {
+ // This is a deep nested association that has not been initialized yet. The controller name
+ // will become the supertitle
+ $vv_subnavigation_tabsSupertitle = Inflector::humanize($vv_controller);
+ } else {
+ // If we get here, it means that neither the request object nor its parent can give us a supertitle.
+ // We need to fetch all the ids and get the supertitle from the root tab/node
+ $results = [];
+ TableUtilities::treeTraversalFromId(StringUtilities::entityToClassName($object), (int)$object->id, $results);
+ $superTitleModelReference = $this->Tab->getModelTableReference($vv_subnavigation_tabs[0]);
+ $superTitleModelDisplayField = $superTitleModelReference->getDisplayField();
+ $superTitleModelId = $results[$vv_subnavigation_tabs[0]];
- $root_obj = $superTitleModelReference->get($superTitleModelId);
- $vv_subnavigation_tabsSupertitle = $root_obj->$superTitleModelDisplayField;
+ $root_obj = $superTitleModelReference->get($superTitleModelId);
+ $vv_subnavigation_tabsSupertitle = $root_obj->$superTitleModelDisplayField;
+ }
}
$supertitle = match (true) {
diff --git a/app/webroot/css/co-base.css b/app/webroot/css/co-base.css
index 92584f03..799fa3b0 100644
--- a/app/webroot/css/co-base.css
+++ b/app/webroot/css/co-base.css
@@ -1001,6 +1001,21 @@ ul.form-list li.alert-banner .co-alert {
white-space: nowrap;
margin-right: 0.5em;
}
+/* PETITION PREVIEW */
+a.cm-toggle {
+ float: right;
+ border: none;
+ background-color: transparent;
+}
+a.cm-toggle .material-symbols,
+a.cm-toggle .material-symbols-outlined{
+ color: var(--cmg-color-headings);
+}
+a.cm-toggle .material-symbols,
+a.cm-toggle .material-symbols-outlined {
+ font-size: 34px;
+ line-height: 17px;
+}
/* PLATFORM NOTICE (for COmanage CO) */
#platform-notice {
padding: 0.5em;
diff --git a/app/webroot/js/comanage/comanage.js b/app/webroot/js/comanage/comanage.js
index dd8b88ab..a6e331d2 100644
--- a/app/webroot/js/comanage/comanage.js
+++ b/app/webroot/js/comanage/comanage.js
@@ -423,4 +423,31 @@ function setApplicationState(value, elem, reload= false) {
generateFlash("" + errorThrown + " (" + jqXHR.status + ")", 'error')
}
});
+}
+
+function stepCollapseToggle(event, item) {
+ /**
+ * Toggles the expanded or collapsed state of the step element.
+ *
+ * This function prevents the default action and stops the propagation of the event,
+ * then toggles the "collapsed" class for the given element. It also updates
+ * the `aria-expanded` attribute and changes the icon displayed within the element.
+ *
+ * - If the element is collapsed, it sets `aria-expanded` to "false" and updates
+ * the icon to "arrow_drop_down."
+ * - If the element is expanded, it sets `aria-expanded` to "true" and updates
+ * the icon to "arrow_drop_up."
+ *
+ * @param {Event} event - The event triggered, usually by a click action.
+ * @param {HTMLElement} item - The DOM element being toggled that represents the step.
+ */
+ event.preventDefault();
+ event.stopPropagation();
+ if ($(item).hasClass("collapsed")) {
+ $(item).attr("aria-expanded","false")
+ $(item).find('em').text("arrow_drop_down");
+ } else {
+ $(item).attr("aria-expanded","true")
+ $(item).find('em').text("arrow_drop_up");
+ }
}
\ No newline at end of file