From 6d62c55c93eac7bad7c941fdaf2e9e14612cd1c4 Mon Sep 17 00:00:00 2001 From: Ioannis Igoumenos Date: Thu, 24 Oct 2024 19:30:33 +0300 Subject: [PATCH] Add support for attribute collection fieldsets --- .../Model/Table/EnrollmentAttributesTable.php | 7 +- .../AttributeCollectors/attribute.inc | 107 +++++++ .../AttributeCollectors/dispatch.inc | 78 +----- .../multifield_attribute.inc | 89 ++++++ .../Controller/StandardEnrollerController.php | 9 +- app/src/Lib/Util/CountryCodeUtilities.php | 263 ++++++++++++++++++ 6 files changed, 474 insertions(+), 79 deletions(-) create mode 100644 app/plugins/CoreEnroller/templates/AttributeCollectors/attribute.inc create mode 100644 app/plugins/CoreEnroller/templates/AttributeCollectors/multifield_attribute.inc create mode 100644 app/src/Lib/Util/CountryCodeUtilities.php diff --git a/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php b/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php index cee5f79a1..707a34062 100644 --- a/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php +++ b/app/plugins/CoreEnroller/src/Model/Table/EnrollmentAttributesTable.php @@ -155,7 +155,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', diff --git a/app/plugins/CoreEnroller/templates/AttributeCollectors/attribute.inc b/app/plugins/CoreEnroller/templates/AttributeCollectors/attribute.inc new file mode 100644 index 000000000..d8dec4a3c --- /dev/null +++ b/app/plugins/CoreEnroller/templates/AttributeCollectors/attribute.inc @@ -0,0 +1,107 @@ +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/dispatch.inc b/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc index a90b43221..92b35e72b 100644 --- a/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc +++ b/app/plugins/CoreEnroller/templates/AttributeCollectors/dispatch.inc @@ -57,80 +57,10 @@ foreach($vv_enrollment_attributes_sorted as $attr) { // 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']]); - continue; + if(empty($attr->attribute_required_fields)) { + include( $vv_template_path . DS . 'attribute.inc'); + } else { + include( $vv_template_path . DS . 'multifield_attribute.inc'); } - // Print the element - print $this->element('form/listItem', [ - 'arguments' => $formArguments - ]); } \ 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 new file mode 100644 index 000000000..e9bd8019e --- /dev/null +++ b/app/plugins/CoreEnroller/templates/AttributeCollectors/multifield_attribute.inc @@ -0,0 +1,89 @@ +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] . ' ' . ucfirst($attr->attribute); +} + +$required_fields_variable_name = "required_fields_$attr->attribute"; +$permitted_fields_variable_name = "permitted_fields_$attr->attribute"; +$permitted_fields_list = []; +$required_fields_list = []; +if (!empty($cosettings[0][$required_fields_variable_name])) { + $required_fields_list = explode(',', $cosettings[0][$required_fields_variable_name]); +} + +if (!empty($cosettings[0][$permitted_fields_variable_name])) { + $permitted_fields_list = explode(',', $cosettings[0][$permitted_fields_variable_name]); +} +?> + +
  • +
    + + + +
    + +attribute_required_fields) as $field) : ?> + + "field-$field-$attr->id", + 'fieldLabel' => $attr->label, // fieldLabel is only applicable to checkboxes + 'fieldType' => $supportedAttributes['fieldType'], + 'fieldNameAlias' => $attr->attribute // the field name to its enrollment attribute field name + ]; +?> + +
    + + element('form/requiredSpan') : ''?> +
    + Field->formField(...$formArguments) ?> +
    +
    + + +
    +
    +
  • diff --git a/app/src/Controller/StandardEnrollerController.php b/app/src/Controller/StandardEnrollerController.php index 601141bbf..25d0a78c6 100644 --- a/app/src/Controller/StandardEnrollerController.php +++ b/app/src/Controller/StandardEnrollerController.php @@ -55,10 +55,11 @@ public function beforeRender(\Cake\Event\EventInterface $event) { // Make the Petition available to the view $this->set( 'vv_petition', - $Petition->findById($this->petition->id) - ->contain($Petition->getIndexContains()) - ->firstOrFail() - ); + $this->petition?->id ? + $Petition->findById($this->petition->id) + ->contain($Petition->getIndexContains()) + ->firstOrFail() : null + ); return parent::beforeRender($event); } diff --git a/app/src/Lib/Util/CountryCodeUtilities.php b/app/src/Lib/Util/CountryCodeUtilities.php new file mode 100644 index 000000000..aea299ad9 --- /dev/null +++ b/app/src/Lib/Util/CountryCodeUtilities.php @@ -0,0 +1,263 @@ + 'UK (+44)', + 1 => 'USA (+1)', + 213 => 'Algeria (+213)', + 376 => 'Andorra (+376)', + 244 => 'Angola (+244)', + 1264 => 'Anguilla (+1264)', + 1268 => 'Antigua & Barbuda (+1268)', + 54 => 'Argentina (+54)', + 374 => 'Armenia (+374)', + 297 => 'Aruba (+297)', + 61 => 'Australia (+61)', + 43 => 'Austria (+43)', + 994 => 'Azerbaijan (+994)', + 1242 => 'Bahamas (+1242)', + 973 => 'Bahrain (+973)', + 880 => 'Bangladesh (+880)', + 1246 => 'Barbados (+1246)', + 375 => 'Belarus (+375)', + 32 => 'Belgium (+32)', + 501 => 'Belize (+501)', + 229 => 'Benin (+229)', + 1441 => 'Bermuda (+1441)', + 975 => 'Bhutan (+975)', + 591 => 'Bolivia (+591)', + 387 => 'Bosnia Herzegovina (+387)', + 267 => 'Botswana (+267)', + 55 => 'Brazil (+55)', + 673 => 'Brunei (+673)', + 359 => 'Bulgaria (+359)', + 226 => 'Burkina Faso (+226)', + 257 => 'Burundi (+257)', + 855 => 'Cambodia (+855)', + 237 => 'Cameroon (+237)', + 1 => 'Canada (+1)', + 238 => 'Cape Verde Islands (+238)', + 1345 => 'Cayman Islands (+1345)', + 236 => 'Central African Republic (+236)', + 56 => 'Chile (+56)', + 86 => 'China (+86)', + 57 => 'Colombia (+57)', + 269 => 'Comoros (+269)', + 242 => 'Congo (+242)', + 682 => 'Cook Islands (+682)', + 506 => 'Costa Rica (+506)', + 385 => 'Croatia (+385)', + 53 => 'Cuba (+53)', + 90392 => 'Cyprus North (+90392)', + 357 => 'Cyprus South (+357)', + 42 => 'Czech Republic (+42)', + 45 => 'Denmark (+45)', + 253 => 'Djibouti (+253)', + 1809 => 'Dominica (+1809)', + 1809 => 'Dominican Republic (+1809)', + 593 => 'Ecuador (+593)', + 20 => 'Egypt (+20)', + 503 => 'El Salvador (+503)', + 240 => 'Equatorial Guinea (+240)', + 291 => 'Eritrea (+291)', + 372 => 'Estonia (+372)', + 251 => 'Ethiopia (+251)', + 500 => 'Falkland Islands (+500)', + 298 => 'Faroe Islands (+298)', + 679 => 'Fiji (+679)', + 358 => 'Finland (+358)', + 33 => 'France (+33)', + 594 => 'French Guiana (+594)', + 689 => 'French Polynesia (+689)', + 241 => 'Gabon (+241)', + 220 => 'Gambia (+220)', + 7880 => 'Georgia (+7880)', + 49 => 'Germany (+49)', + 233 => 'Ghana (+233)', + 350 => 'Gibraltar (+350)', + 30 => 'Greece (+30)', + 299 => 'Greenland (+299)', + 1473 => 'Grenada (+1473)', + 590 => 'Guadeloupe (+590)', + 671 => 'Guam (+671)', + 502 => 'Guatemala (+502)', + 224 => 'Guinea (+224)', + 245 => 'Guinea - Bissau (+245)', + 592 => 'Guyana (+592)', + 509 => 'Haiti (+509)', + 504 => 'Honduras (+504)', + 852 => 'Hong Kong (+852)', + 36 => 'Hungary (+36)', + 354 => 'Iceland (+354)', + 91 => 'India (+91)', + 62 => 'Indonesia (+62)', + 98 => 'Iran (+98)', + 964 => 'Iraq (+964)', + 353 => 'Ireland (+353)', + 972 => 'Israel (+972)', + 39 => 'Italy (+39)', + 1876 => 'Jamaica (+1876)', + 81 => 'Japan (+81)', + 962 => 'Jordan (+962)', + 7 => 'Kazakhstan (+7)', + 254 => 'Kenya (+254)', + 686 => 'Kiribati (+686)', + 850 => 'Korea North (+850)', + 82 => 'Korea South (+82)', + 965 => 'Kuwait (+965)', + 996 => 'Kyrgyzstan (+996)', + 856 => 'Laos (+856)', + 371 => 'Latvia (+371)', + 961 => 'Lebanon (+961)', + 266 => 'Lesotho (+266)', + 231 => 'Liberia (+231)', + 218 => 'Libya (+218)', + 417 => 'Liechtenstein (+417)', + 370 => 'Lithuania (+370)', + 352 => 'Luxembourg (+352)', + 853 => 'Macao (+853)', + 389 => 'Macedonia (+389)', + 261 => 'Madagascar (+261)', + 265 => 'Malawi (+265)', + 60 => 'Malaysia (+60)', + 960 => 'Maldives (+960)', + 223 => 'Mali (+223)', + 356 => 'Malta (+356)', + 692 => 'Marshall Islands (+692)', + 596 => 'Martinique (+596)', + 222 => 'Mauritania (+222)', + 269 => 'Mayotte (+269)', + 52 => 'Mexico (+52)', + 691 => 'Micronesia (+691)', + 373 => 'Moldova (+373)', + 377 => 'Monaco (+377)', + 976 => 'Mongolia (+976)', + 1664 => 'Montserrat (+1664)', + 212 => 'Morocco (+212)', + 258 => 'Mozambique (+258)', + 95 => 'Myanmar (+95)', + 264 => 'Namibia (+264)', + 674 => 'Nauru (+674)', + 977 => 'Nepal (+977)', + 31 => 'Netherlands (+31)', + 687 => 'New Caledonia (+687)', + 64 => 'New Zealand (+64)', + 505 => 'Nicaragua (+505)', + 227 => 'Niger (+227)', + 234 => 'Nigeria (+234)', + 683 => 'Niue (+683)', + 672 => 'Norfolk Islands (+672)', + 670 => 'Northern Marianas (+670)', + 47 => 'Norway (+47)', + 968 => 'Oman (+968)', + 680 => 'Palau (+680)', + 507 => 'Panama (+507)', + 675 => 'Papua New Guinea (+675)', + 595 => 'Paraguay (+595)', + 51 => 'Peru (+51)', + 63 => 'Philippines (+63)', + 48 => 'Poland (+48)', + 351 => 'Portugal (+351)', + 1787 => 'Puerto Rico (+1787)', + 974 => 'Qatar (+974)', + 262 => 'Reunion (+262)', + 40 => 'Romania (+40)', + 7 => 'Russia (+7)', + 250 => 'Rwanda (+250)', + 378 => 'San Marino (+378)', + 239 => 'Sao Tome & Principe (+239)', + 966 => 'Saudi Arabia (+966)', + 221 => 'Senegal (+221)', + 381 => 'Serbia (+381)', + 248 => 'Seychelles (+248)', + 232 => 'Sierra Leone (+232)', + 65 => 'Singapore (+65)', + 421 => 'Slovak Republic (+421)', + 386 => 'Slovenia (+386)', + 677 => 'Solomon Islands (+677)', + 252 => 'Somalia (+252)', + 27 => 'South Africa (+27)', + 34 => 'Spain (+34)', + 94 => 'Sri Lanka (+94)', + 290 => 'St. Helena (+290)', + 1869 => 'St. Kitts (+1869)', + 1758 => 'St. Lucia (+1758)', + 249 => 'Sudan (+249)', + 597 => 'Suriname (+597)', + 268 => 'Swaziland (+268)', + 46 => 'Sweden (+46)', + 41 => 'Switzerland (+41)', + 963 => 'Syria (+963)', + 886 => 'Taiwan (+886)', + 7 => 'Tajikstan (+7)', + 66 => 'Thailand (+66)', + 228 => 'Togo (+228)', + 676 => 'Tonga (+676)', + 1868 => 'Trinidad & Tobago (+1868)', + 216 => 'Tunisia (+216)', + 90 => 'Turkey (+90)', + 7 => 'Turkmenistan (+7)', + 993 => 'Turkmenistan (+993)', + 1649 => 'Turks & Caicos Islands (+1649)', + 688 => 'Tuvalu (+688)', + 256 => 'Uganda (+256)', + 380 => 'Ukraine (+380)', + 971 => 'United Arab Emirates (+971)', + 598 => 'Uruguay (+598)', + 7 => 'Uzbekistan (+7)', + 678 => 'Vanuatu (+678)', + 379 => 'Vatican City (+379)', + 58 => 'Venezuela (+58)', + 84 => 'Vietnam (+84)', + 84 => 'Virgin Islands - British (+1284)', + 84 => 'Virgin Islands - US (+1340)', + 681 => 'Wallis & Futuna (+681)', + 969 => 'Yemen (North)(+969)', + 967 => 'Yemen (South)(+967)', + 260 => 'Zambia (+260)', + 263 => 'Zimbabwe (+263)', + ]; + + return $ccodes[$code] ?? $ccodes; + } +} \ No newline at end of file