diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc b/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc
index 92b35e72b..95288d700 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,13 +53,12 @@ foreach($vv_enrollment_attributes_sorted as $attr) {
continue;
}
- // Get the static configuration of my attribute
- $supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
-
- if(empty($attr->attribute_required_fields)) {
- include( $vv_template_path . DS . 'attribute.inc');
- } else {
- include( $vv_template_path . DS . 'multifield_attribute.inc');
+ // Fieldset with legend for MVEAs
+ if(\in_array($attr->attribute, ['name', 'address', 'telephoneNumber'], true)) {
+ print $this->element('CoreEnroller.mveas/mvea-fieldset', compact('attr'));
+ continue;
}
+ // Default
+ print $this->element('CoreEnroller.field', compact('attr'));
}
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/multifield_attribute.inc b/app/plugins/CoreEnroller/templates/AttributeCollectors/multifield_attribute.inc
deleted file mode 100644
index f416f1e66..000000000
--- a/app/plugins/CoreEnroller/templates/AttributeCollectors/multifield_attribute.inc
+++ /dev/null
@@ -1,107 +0,0 @@
-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));
-}
-
-$required_fields_variable_name = 'required_fields_' . Inflector::underscore($attr->attribute);
-$permitted_fields_variable_name = 'permitted_fields_' . Inflector::underscore($attr->attribute);
-$permitted_fields_list = [];
-$required_fields_list = [];
-
-if (!empty($cosettings[0][$permitted_fields_variable_name])) {
- $permitted_fields_list = explode(',', $cosettings[0][$permitted_fields_variable_name]);
-}
-
-// Required fields
-// - first look at the enrollment flow level
-// - if not set look at the co level
-$required_fields = match(true) {
- // Enrollment Flow
- !empty($attr?->attribute_required_fields) => $attr?->attribute_required_fields,
- // Co Level
- !empty($cosettings[0][$required_fields_variable_name]) => $cosettings[0][$required_fields_variable_name],
- // XXX Do i need CMP level here?
- default => ''
-};
-// List of the required fields
-$required_fields_list = explode(',', $required_fields);
-
-// Address has not permitted fields configuration at CO level. And according to our design,
-// the permitted fields are found in CoSettings. As a result, if we do not have any we need to get
-// For all the attributes that have no
-// permitted configuration at the CO level we will get all the fields that we support
-$requiredDropDownListVar = $attr->attribute . 'RequiredFields';
-if(empty($permitted_fields_list) && !empty($$requiredDropDownListVar)) {
- usort($$requiredDropDownListVar, static fn($a, $b) => count(explode(',', $a)) <=> count(explode(',', $b)));
- $permitted_fields = end($$requiredDropDownListVar);
- $permitted_fields_list = collection(explode(',', $permitted_fields))->map(fn($value) => trim($value));
-}
-
-// Grouped fields
-$groupedFieldsVar = $attr->attribute . 'GroupedFields';
-$groupedFieldsArray = [];
-if(!empty($$groupedFieldsVar)) {
- $groupedFieldsArray = collection(array_keys($$groupedFieldsVar))->map(static fn($fields) => explode(',', $fields))->toArray();
-}
-// Now that we have the permitted fields array and the grouped fields array, we need to put the permitted fields to groups
-
-?>
-
-
-
-
diff --git a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
index dc30198bb..441ae7d28 100644
--- a/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
+++ b/app/plugins/CoreEnroller/templates/EnrollmentAttributes/fields.inc
@@ -172,8 +172,10 @@ if (\in_array($attribute_type, ['adHocAttribute'], true)) {
* Attribute Language field
*
* Supported for attributes: name, address
+ * todo: probably should go away. The attribute required fields could become hidden and store what we have in CoSettings
+ * at the time we saved the required fields.
*/
-if(\in_array($attribute_type, ['name', 'address', 'pronoun'], true)) {
+if(\in_array($attribute_type, ['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) {
diff --git a/app/plugins/CoreEnroller/templates/element/field.php b/app/plugins/CoreEnroller/templates/element/field.php
new file mode 100644
index 000000000..0aa16367d
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/field.php
@@ -0,0 +1,110 @@
+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;
+}
+
+// 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']]);
+} else {
+ // Print the element
+ print $this->element('form/listItem', [
+ 'arguments' => $formArguments
+ ]);
+}
\ No newline at end of file
diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/fieldset-field.inc b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
similarity index 72%
rename from app/plugins/CoreEnroller/templates/AttributeCollectors/fieldset-field.inc
rename to app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
index 4e112d6e4..95820190d 100644
--- a/app/plugins/CoreEnroller/templates/AttributeCollectors/fieldset-field.inc
+++ b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-field.php
@@ -1,6 +1,6 @@
Petition->getSupportedEnrollmentAttribute($attr->attribute);
+
+if(isset($supportedAttributes['mveaModel'])) {
+ $supportedAttributes = $this->Petition->getSupportedEnrollmentAttribute($attr->attribute);
+ $tableValidator = $this->Petition->getTableValidator($supportedAttributes['mveaModel']);
+ $isRequiredFromValidationRule = !$tableValidator->field($field)->isEmptyAllowed();
+}
// Construct the field arguments
$formArguments = [
@@ -47,8 +57,11 @@
\ No newline at end of file
+
+
+
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 000000000..fa7adc356
--- /dev/null
+++ b/app/plugins/CoreEnroller/templates/element/mveas/fieldset-group.php
@@ -0,0 +1,86 @@
+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. And according to our design,
+// the permitted fields are found in CoSettings.
+// For all the attributes that have no permitted configuration at the CO level,
+// we will get all the fields that we support
+// We will construct the list of permitted fields from the list of required fields.
+// The permitted fields will be the set that contains all the required fields.
+$requiredDropDownListVar = $attr->attribute . 'RequiredFields';
+if(empty($permitted_fields_list) && !empty($$requiredDropDownListVar)) {
+ usort($$requiredDropDownListVar, static fn($a, $b) => count(explode(',', $a)) <=> count(explode(',', $b)));
+ $permitted_fields = end($$requiredDropDownListVar);
+ $permitted_fields_list = collection(explode(',', $permitted_fields))->map(fn($value) => trim($value));
+}
+
+?>
+
+ $fields): ?>
+
+ map(static fn($value) => str_replace(' ', '_', Inflector::underscore($value)));
+ foreach($fields as $field) {
+ if($permitted_fields_list->contains($field)) {
+ // Print the element
+ print $this->element('CoreEnroller.mveas/fieldset-field', compact('field', 'attr'));
+ }
+ // Remove the field we render from the permitted list.
+ $permitted_fields_list = $permitted_fields_list->filter(fn($value) => $value !== $field);
+ }
+ ?>
+
+
+
+element('CoreEnroller.mveas/fieldset-field', compact('field', 'attr'));
+}
+?>
+
+
diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/fieldset-group.inc b/app/plugins/CoreEnroller/templates/element/mveas/mvea-fieldset.php
similarity index 54%
rename from app/plugins/CoreEnroller/templates/AttributeCollectors/fieldset-group.inc
rename to app/plugins/CoreEnroller/templates/element/mveas/mvea-fieldset.php
index 3bc6ff24d..9bda744ab 100644
--- a/app/plugins/CoreEnroller/templates/AttributeCollectors/fieldset-group.inc
+++ b/app/plugins/CoreEnroller/templates/element/mveas/mvea-fieldset.php
@@ -1,6 +1,6 @@
-
- $fields): ?>
-
-
-
-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));
}
-?>
+?>
+
+
+
diff --git a/app/src/Controller/StandardEnrollerController.php b/app/src/Controller/StandardEnrollerController.php
index 25d0a78c6..e320eb39f 100644
--- a/app/src/Controller/StandardEnrollerController.php
+++ b/app/src/Controller/StandardEnrollerController.php
@@ -57,7 +57,10 @@ public function beforeRender(\Cake\Event\EventInterface $event) {
'vv_petition',
$this->petition?->id ?
$Petition->findById($this->petition->id)
- ->contain($Petition->getIndexContains())
+ // We need to include the Enrollment Flow of the Petition.
+ // The least, we can get if the co id which cannot be calculated
+ // for unauthenticated use cases.
+ ->contain(['EnrollmentFlows'])
->firstOrFail() : null
);
diff --git a/app/src/Lib/Enum/RequiredAddressFieldsEnum.php b/app/src/Lib/Enum/RequiredAddressFieldsEnum.php
index 4ad59395c..a2e2a4bbd 100644
--- a/app/src/Lib/Enum/RequiredAddressFieldsEnum.php
+++ b/app/src/Lib/Enum/RequiredAddressFieldsEnum.php
@@ -34,6 +34,6 @@ class RequiredAddressFieldsEnum extends StandardEnum {
const Country = "country";
const Postal = "postal_code";
const Street = "street";
- const StreetCityStatePostal = "street,locality,state,postal_code";
- const StreetCityStatePostalCountry = "street,locality,state,postal_code,country";
+ const StreetCityStatePostal = "street,room,locality,state,postal_code";
+ const StreetCityStatePostalCountry = "street,room,locality,state,postal_code,country";
}
\ No newline at end of file
diff --git a/app/src/View/Helper/PetitionHelper.php b/app/src/View/Helper/PetitionHelper.php
index eea417c3a..91234d80a 100644
--- a/app/src/View/Helper/PetitionHelper.php
+++ b/app/src/View/Helper/PetitionHelper.php
@@ -34,6 +34,7 @@
use Cake\ORM\Table;
use Cake\ORM\TableRegistry;
use Cake\Utility\Inflector;
+use Cake\Validation\Validator;
use Cake\View\Helper;
use CoreEnroller\Model\Table\EnrollmentAttributesTable;
@@ -81,4 +82,18 @@ public function populateAutoViewVars(): void
$this->getView()->set($vvar, $value);
}
}
+
+ /**
+ * Get the table validation rules
+ *
+ * @param string $tableName
+ *
+ * @return Validator
+ * @since COmanage Registry v5.0.0
+ */
+ public function getTableValidator(string $tableName): \Cake\Validation\Validator
+ {
+ $ModelTable = TableRegistry::getTableLocator()->get($tableName);
+ return $ModelTable->getValidator();// For MVEAs we retrieve the validation rules from CoSettings. Telephone numbers are different
+ }
}
\ No newline at end of file