diff --git a/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php b/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php
index 5ed3d6aa..1ec67cea 100644
--- a/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php
+++ b/app/plugins/CoreEnroller/src/Model/Table/BasicAttributeCollectorsTable.php
@@ -45,6 +45,7 @@ class BasicAttributeCollectorsTable extends Table {
use \App\Lib\Traits\PrimaryLinkTrait;
use \App\Lib\Traits\TableMetaTrait;
use \App\Lib\Traits\ValidationTrait;
+ use \App\Lib\Traits\LayoutTrait;
/**
* Perform Cake Model initialization.
diff --git a/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php b/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php
index cee5f79a..3ca48ba2 100644
--- a/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php
+++ b/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php
@@ -85,6 +85,10 @@ public function initialize(array $config): void {
'type' => 'enum',
'class' => 'RequiredAddressFieldsEnum'
],
+ 'addressGroupedFields' => [
+ 'type' => 'enum',
+ 'class' => 'GroupedAddressFieldsEnum'
+ ],
'addressTypes' => [
'type' => 'type',
'attribute' => 'Addresses.type'
@@ -155,7 +159,12 @@ public function initialize(array $config): void {
'urlTypes' => [
'type' => 'type',
'attribute' => 'Urls.type'
- ]
+ ],
+ // Required for attribute collection
+ 'cosettings' => [
+ 'type' => 'auxiliary',
+ 'model' => 'CoSettings'
+ ],
]);
$this->setLayout([ 'index' => 'iframe',
@@ -404,8 +413,6 @@ public function validationDefault(Validator $validator): Validator {
]);
$validator->allowEmptyString('attribute_mvea_parent');
- $this->registerStringValidation($validator, $schema, 'attribute_required_fields', false);
-
$this->registerStringValidation($validator, $schema, 'attribute_tag', false);
$validator->add('status', [
diff --git a/app/plugins/CoreEnroller/src/config/plugin.json b/app/plugins/CoreEnroller/src/config/plugin.json
index 158bf233..679d2cf6 100644
--- a/app/plugins/CoreEnroller/src/config/plugin.json
+++ b/app/plugins/CoreEnroller/src/config/plugin.json
@@ -72,7 +72,6 @@
"attribute_type": { "type": "integer", "foreignkey": { "table": "types", "column": "id" } },
"attribute_language": { "type": "string", "size": 16 },
"attribute_mvea_parent": { "type": "string", "size": 32 },
- "attribute_required_fields": { "type": "string", "size": 160 },
"attribute_tag": { "type": "string", "size": 128 },
"status": {},
"label": { "type": "string", "size": 80 },
diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc b/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc
index a90b4322..95288d70 100644
--- a/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc
+++ b/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc
@@ -28,7 +28,6 @@
declare(strict_types = 1);
use App\Lib\Enum\StatusEnum;
-use \Cake\Utility\Inflector;
// This view is intended to work with dispatch
if($vv_action !== 'dispatch') {
@@ -54,83 +53,12 @@ foreach($vv_enrollment_attributes_sorted as $attr) {
continue;
}
- // Get the static configuration of my attribute
- $supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
-
- // Field Options array
- $options = [];
-
-
- // 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,
- 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 rerendering 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]);
-
- 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
- // problems with field names that are purely integers (even if cast to strings)
- 'fieldName' => 'field-' . $attr->id,
- 'fieldLabel' => $attr->label, // fieldLabel is only applicable to checkboxes
- 'fieldType' => $supportedAttributes['fieldType'],
- 'fieldDescription' => $attr->description,
- 'fieldNameAlias' => $attr->attribute // the field name to its enrollment attribute field name
- ];
-
-
- /*
- * Get the values for the attributes ending with _id
- * Supported for attributes: group_id, cou_id, affiliation_type_id
- */
- if(str_ends_with($attr->attribute, '_id')) {
- $suffix = substr($attr->attribute, 0, -3);
- $suffix = Inflector::pluralize(Inflector::camelize($suffix)) ;
- $defaultValuesPopulated = 'defaultValue' . $suffix;
- if ($this->get($defaultValuesPopulated) !== null) {
- $formArguments['fieldType'] = 'select';
- $formArguments['fieldSelectOptions'] = $this->get($defaultValuesPopulated);
- }
- }
-
- // READ-ONLY
- if (isset($attr->modifiable) && !$attr->modifiable) {
- $options['readonly'] = true;
- }
-
- // REQUIRED
- if (isset($attr->required) && $attr->required) {
- $options['required'] = true;
- }
-
- // Set the final fieldOptions
- $formArguments['fieldOptions'] = $options;
-
- // HIDDEN Field
- // We print directly, we do not delegate to the element for further processing
- if ($attr->hidden) {
- // In case this is a hidden field, we need to get only the value
- print $this->Form->hidden($formArguments['fieldName'], ['value' => $options['default']]);
+ // Fieldset with legend for MVEAs
+ if(\in_array($attr->attribute, ['name', 'address', 'telephoneNumber'], true)) {
+ print $this->element('CoreEnroller.mveas/mvea-fieldset', compact('attr'));
continue;
}
- // Print the element
- print $this->element('form/listItem', [
- 'arguments' => $formArguments
- ]);
+ // Default
+ print $this->element('CoreEnroller.field', compact('attr'));
}
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
index dc30198b..9b17608f 100644
--- a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
+++ b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
@@ -168,30 +168,9 @@ if (\in_array($attribute_type, ['adHocAttribute'], true)) {
}
/*
- * Attribute Required field
* Attribute Language field
- *
- * Supported for attributes: name, address
*/
if(\in_array($attribute_type, ['name', 'address', 'pronoun'], true)) {
- $requiredFieldsPopulated = $attribute_type . 'RequiredFields';
- // Pronouns have no required fields at the moment, as a result we will not render any.
- if ($this->get($requiredFieldsPopulated) !== null) {
- $label = __d('core_enroller', 'field.EnrollmentAttributes.' . $attribute_type . '_required_fields');
- print $this->element('form/listItem', [
- 'arguments' => [
- 'fieldLabel' => $label,
- 'fieldName' => 'attribute_required_fields',
- 'fieldOptions' => [
- 'empty' => true
- ],
- 'fieldType' => 'select',
- 'fieldSelectOptions' => $this->get($requiredFieldsPopulated)
- ]
- ]);
- }
-
-
print $this->element('form/listItem', [
'arguments' => [
'fieldName' => 'attribute_language',
diff --git a/app/plugins/CoreEnroller/templates/element/field.php b/app/plugins/CoreEnroller/templates/element/field.php
new file mode 100644
index 00000000..68e4be12
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/field.php
@@ -0,0 +1,118 @@
+Petition->getSupportedEnrollmentAttribute($attr->attribute);
+
+// 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,
+ 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]);
+
+ 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
+ // problems with field names that are purely integers (even if cast to strings)
+ 'fieldName' => 'field-' . $attr->id,
+ 'fieldLabel' => $attr->label, // fieldLabel is only applicable to checkboxes
+ 'fieldType' => $supportedAttributes['fieldType'],
+ 'fieldDescription' => $attr->description,
+ 'fieldNameAlias' => $attr->attribute // the field name to its enrollment attribute field name
+];
+
+
+/*
+ * Get the values for the attributes ending with _id
+ * Supported for attributes: group_id, cou_id, affiliation_type_id
+ */
+if(str_ends_with($attr->attribute, '_id')) {
+ $suffix = substr($attr->attribute, 0, -3);
+ $suffix = Inflector::pluralize(Inflector::camelize($suffix)) ;
+ $defaultValuesPopulated = 'defaultValue' . $suffix;
+ if ($this->get($defaultValuesPopulated) !== null) {
+ $formArguments['fieldType'] = 'select';
+ $formArguments['fieldSelectOptions'] = $this->get($defaultValuesPopulated);
+ }
+}
+
+// READ-ONLY
+if (isset($attr->modifiable) && !$attr->modifiable) {
+ $options['readonly'] = true;
+}
+
+// REQUIRED
+if (isset($attr->required) && $attr->required) {
+ $options['required'] = true;
+}
+
+$hidden = true;
+// XXX We need to render a field that is required and expects a value from the environment but
+// the env value is empty.
+if (
+ isset($attr->default_value_env_name, $attr->required)
+ && empty($options['default'])
+ && $attr->required
+) {
+ $hidden = false;
+}
+
+// Set the final fieldOptions
+$formArguments['fieldOptions'] = $options;
+
+print match(true) {
+ // HIDDEN Field
+ // We print directly, we do not delegate to the element for further processing
+ // In case this is a hidden field, we need to get only the value
+ $attr->hidden && $hidden =>$this->Form->hidden($formArguments['fieldName'], ['value' => $options['default']]),
+ // Default use case
+ default => $this->element('form/listItem', ['arguments' => $formArguments])
+};
diff --git a/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
new file mode 100644
index 00000000..58c89298
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
@@ -0,0 +1,64 @@
+Petition->getSupportedEnrollmentAttribute($attr->attribute);
+
+if(isset($supportedAttributes['mveaModel'])) {
+ $supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
+ $modelTable = $this->Petition->getTable($supportedAttributes['mveaModel']);
+ $isRequiredFromValidationRule = !$modelTable->getValidator()->field($field)->isEmptyAllowed();
+}
+
+// Construct the field arguments
+$formArguments = [
+ // We prefix the attribute ID with a string because Cake seems to sometimes have
+ // problems with field names that are purely integers (even if cast to strings)
+ 'fieldName' => "field-$field-$attr->id",
+ 'fieldLabel' => $attr->label, // fieldLabel is only applicable to checkboxes
+ 'fieldType' => $modelTable->getSchema()->getColumn($field)['type'],
+ 'fieldNameAlias' => $attr->attribute // the field name to its enrollment attribute field name
+];
+?>
+
+
+
+
diff --git a/app/plugins/CoreEnroller/templates/element/mveas/fieldset-group.php b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-group.php
new file mode 100644
index 00000000..380e77e8
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-group.php
@@ -0,0 +1,81 @@
+attribute . 'GroupedFields';
+$groupedFieldsArray = [];
+if(!empty($$groupedFieldsVar)) {
+ $groupedFieldsArray = collection(array_keys($$groupedFieldsVar))->map(static fn($fields) => explode(',', $fields))->toArray();
+}
+
+$permitted_fields_list = [];
+$permitted_fields_variable_name = 'permitted_fields_' . Inflector::underscore($attr->attribute);
+if (!empty($cosettings[0][$permitted_fields_variable_name])) {
+ $permitted_fields_list = explode(',', $cosettings[0][$permitted_fields_variable_name]);
+}
+// Address has no permitted fields configuration at CO level. We will get them from
+// the model configuration
+$supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
+$modelTable = $this->Petition->getTable($supportedAttributes['mveaModel']);
+if(empty($permitted_fields_list) && !empty($modelTable?->getPermittedFields())) {
+ $permitted_fields_list = $modelTable->getPermittedFields();
+}
+
+$permitted_fields_list_flipped = array_flip($permitted_fields_list);
+?>
+
+ $fields): ?>
+
+ element('CoreEnroller.mveas/fieldset-field', compact('field', 'attr'));
+ }
+ // Remove the field we rendered from the permitted list.
+ unset($permitted_fields_list_flipped[$field]);
+ }
+ ?>
+
+
+
+element('CoreEnroller.mveas/fieldset-field', compact('field', 'attr'));
+}
+?>
+
+
diff --git a/app/plugins/CoreEnroller/templates/element/mveas/mvea-fieldset.php b/app/plugins/CoreEnroller/templates/element/mveas/mvea-fieldset.php
new file mode 100644
index 00000000..9bda744a
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/mveas/mvea-fieldset.php
@@ -0,0 +1,58 @@
+attribute . 'Types';
+// Check if this mvea model supports types, if it does then render the attribute type
+// dropdown list
+$fieldLabel = 'Not found';
+if ($this->get($mveaAutoPopulatedVariable) !== null) {
+ $fieldLabel = $this->get($mveaAutoPopulatedVariable)[$attr->attribute_type]
+ . ' '
+ . Inflector::humanize(Inflector::underscore($attr->attribute));
+}
+
+?>
+
+