From 89dd54b7673f3e007846e5fe0300351da875d79c Mon Sep 17 00:00:00 2001 From: Paul Pound Date: Thu, 26 Feb 2026 14:54:04 -0400 Subject: [PATCH] added item title field and some validation for emails and phone numbers --- ...y.node.ill_institution_request.default.yml | 59 ++-- ...y.node.ill_institution_request.default.yml | 58 ++-- ...stitution_request.field_ill_item_title.yml | 21 ++ ...itution_request.field_ill_request_type.yml | 21 ++ ...equest.field_ill_system_request_number.yml | 21 ++ ...ield.storage.node.field_ill_item_title.yml | 23 ++ ...ld.storage.node.field_ill_request_type.yml | 26 ++ ...e.node.field_ill_system_request_number.yml | 23 ++ .../views.view.ill_institution_requests.yml | 277 +++++++++++++++++- ill_corporate_forms.module | 83 ++++++ 10 files changed, 577 insertions(+), 35 deletions(-) create mode 100644 config/install/field.field.node.ill_institution_request.field_ill_item_title.yml create mode 100644 config/install/field.field.node.ill_institution_request.field_ill_request_type.yml create mode 100644 config/install/field.field.node.ill_institution_request.field_ill_system_request_number.yml create mode 100644 config/install/field.storage.node.field_ill_item_title.yml create mode 100644 config/install/field.storage.node.field_ill_request_type.yml create mode 100644 config/install/field.storage.node.field_ill_system_request_number.yml diff --git a/config/install/core.entity_form_display.node.ill_institution_request.default.yml b/config/install/core.entity_form_display.node.ill_institution_request.default.yml index 7e1b88c..5ba32aa 100644 --- a/config/install/core.entity_form_display.node.ill_institution_request.default.yml +++ b/config/install/core.entity_form_display.node.ill_institution_request.default.yml @@ -14,6 +14,7 @@ dependencies: - field.field.node.ill_institution_request.field_ill_isbn - field.field.node.ill_institution_request.field_ill_issn - field.field.node.ill_institution_request.field_ill_issue + - field.field.node.ill_institution_request.field_ill_item_title - field.field.node.ill_institution_request.field_ill_item_type - field.field.node.ill_institution_request.field_ill_journal_title - field.field.node.ill_institution_request.field_ill_pages @@ -21,7 +22,9 @@ dependencies: - field.field.node.ill_institution_request.field_ill_publication_date - field.field.node.ill_institution_request.field_ill_publisher - field.field.node.ill_institution_request.field_ill_req_email + - field.field.node.ill_institution_request.field_ill_request_type - field.field.node.ill_institution_request.field_ill_source_of_information + - field.field.node.ill_institution_request.field_ill_system_request_number - field.field.node.ill_institution_request.field_ill_volume - node.type.ill_institution_request module: @@ -49,6 +52,12 @@ content: size: 60 placeholder: '' third_party_settings: {} + field_ill_request_type: + type: options_buttons + weight: 4 + region: content + settings: {} + third_party_settings: {} field_ill_req_email: type: email_default weight: 12 @@ -63,7 +72,7 @@ content: region: content settings: {} third_party_settings: {} - field_ill_author_editor: + field_ill_item_title: type: string_textfield weight: 14 region: content @@ -71,7 +80,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_isbn: + field_ill_author_editor: type: string_textfield weight: 15 region: content @@ -79,7 +88,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_publication_date: + field_ill_isbn: type: string_textfield weight: 16 region: content @@ -87,7 +96,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_edition: + field_ill_publication_date: type: string_textfield weight: 17 region: content @@ -95,7 +104,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_publisher: + field_ill_edition: type: string_textfield weight: 18 region: content @@ -103,7 +112,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_journal_title: + field_ill_publisher: type: string_textfield weight: 19 region: content @@ -111,7 +120,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_article_title: + field_ill_journal_title: type: string_textfield weight: 20 region: content @@ -119,7 +128,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_article_author: + field_ill_article_title: type: string_textfield weight: 21 region: content @@ -127,7 +136,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_volume: + field_ill_article_author: type: string_textfield weight: 22 region: content @@ -135,7 +144,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_issue: + field_ill_volume: type: string_textfield weight: 23 region: content @@ -143,7 +152,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_issn: + field_ill_issue: type: string_textfield weight: 24 region: content @@ -151,7 +160,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_pages: + field_ill_issn: type: string_textfield weight: 25 region: content @@ -159,7 +168,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_chapter_title: + field_ill_pages: type: string_textfield weight: 26 region: content @@ -167,7 +176,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_chapter_author: + field_ill_chapter_title: type: string_textfield weight: 27 region: content @@ -175,7 +184,7 @@ content: size: 60 placeholder: '' third_party_settings: {} - field_ill_source_of_information: + field_ill_chapter_author: type: string_textfield weight: 28 region: content @@ -183,9 +192,25 @@ content: size: 60 placeholder: '' third_party_settings: {} + field_ill_system_request_number: + type: string_textfield + weight: 29 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: {} + field_ill_source_of_information: + type: string_textfield + weight: 30 + region: content + settings: + size: 60 + placeholder: '' + third_party_settings: {} field_ill_additional_notes: type: text_textarea - weight: 29 + weight: 31 region: content settings: rows: 5 @@ -193,7 +218,7 @@ content: third_party_settings: {} field_ill_copyright_agreement: type: boolean_checkbox - weight: 30 + weight: 32 region: content settings: display_label: true diff --git a/config/install/core.entity_view_display.node.ill_institution_request.default.yml b/config/install/core.entity_view_display.node.ill_institution_request.default.yml index c7e3c90..ea3a958 100644 --- a/config/install/core.entity_view_display.node.ill_institution_request.default.yml +++ b/config/install/core.entity_view_display.node.ill_institution_request.default.yml @@ -14,6 +14,7 @@ dependencies: - field.field.node.ill_institution_request.field_ill_isbn - field.field.node.ill_institution_request.field_ill_issn - field.field.node.ill_institution_request.field_ill_issue + - field.field.node.ill_institution_request.field_ill_item_title - field.field.node.ill_institution_request.field_ill_item_type - field.field.node.ill_institution_request.field_ill_journal_title - field.field.node.ill_institution_request.field_ill_pages @@ -21,7 +22,9 @@ dependencies: - field.field.node.ill_institution_request.field_ill_publication_date - field.field.node.ill_institution_request.field_ill_publisher - field.field.node.ill_institution_request.field_ill_req_email + - field.field.node.ill_institution_request.field_ill_request_type - field.field.node.ill_institution_request.field_ill_source_of_information + - field.field.node.ill_institution_request.field_ill_system_request_number - field.field.node.ill_institution_request.field_ill_volume - node.type.ill_institution_request module: @@ -49,6 +52,13 @@ content: label: above settings: {} third_party_settings: {} + field_ill_request_type: + type: list_default + weight: 4 + region: content + label: above + settings: {} + third_party_settings: {} field_ill_req_email: type: email_mailto weight: 12 @@ -63,121 +73,135 @@ content: label: above settings: {} third_party_settings: {} - field_ill_author_editor: + field_ill_item_title: type: string weight: 14 region: content label: above settings: {} third_party_settings: {} - field_ill_isbn: + field_ill_author_editor: type: string weight: 15 region: content label: above settings: {} third_party_settings: {} - field_ill_publication_date: + field_ill_isbn: type: string weight: 16 region: content label: above settings: {} third_party_settings: {} - field_ill_edition: + field_ill_publication_date: type: string weight: 17 region: content label: above settings: {} third_party_settings: {} - field_ill_publisher: + field_ill_edition: type: string weight: 18 region: content label: above settings: {} third_party_settings: {} - field_ill_journal_title: + field_ill_publisher: type: string weight: 19 region: content label: above settings: {} third_party_settings: {} - field_ill_article_title: + field_ill_journal_title: type: string weight: 20 region: content label: above settings: {} third_party_settings: {} - field_ill_article_author: + field_ill_article_title: type: string weight: 21 region: content label: above settings: {} third_party_settings: {} - field_ill_volume: + field_ill_article_author: type: string weight: 22 region: content label: above settings: {} third_party_settings: {} - field_ill_issue: + field_ill_volume: type: string weight: 23 region: content label: above settings: {} third_party_settings: {} - field_ill_issn: + field_ill_issue: type: string weight: 24 region: content label: above settings: {} third_party_settings: {} - field_ill_pages: + field_ill_issn: type: string weight: 25 region: content label: above settings: {} third_party_settings: {} - field_ill_chapter_title: + field_ill_pages: type: string weight: 26 region: content label: above settings: {} third_party_settings: {} - field_ill_chapter_author: + field_ill_chapter_title: type: string weight: 27 region: content label: above settings: {} third_party_settings: {} - field_ill_source_of_information: + field_ill_chapter_author: type: string weight: 28 region: content label: above settings: {} third_party_settings: {} + field_ill_system_request_number: + type: string + weight: 29 + region: content + label: above + settings: {} + third_party_settings: {} + field_ill_source_of_information: + type: string + weight: 30 + region: content + label: above + settings: {} + third_party_settings: {} field_ill_additional_notes: type: text_default - weight: 29 + weight: 31 region: content label: above settings: {} third_party_settings: {} field_ill_copyright_agreement: type: boolean - weight: 30 + weight: 32 region: content label: above settings: {} diff --git a/config/install/field.field.node.ill_institution_request.field_ill_item_title.yml b/config/install/field.field.node.ill_institution_request.field_ill_item_title.yml new file mode 100644 index 0000000..175c0ff --- /dev/null +++ b/config/install/field.field.node.ill_institution_request.field_ill_item_title.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_ill_item_title + - node.type.ill_institution_request + enforced: + module: + - ill_corporate_forms +id: node.ill_institution_request.field_ill_item_title +field_name: field_ill_item_title +entity_type: node +bundle: ill_institution_request +label: 'Item Title' +description: '' +required: false +translatable: false +default_value: {} +default_value_callback: '' +settings: {} +field_type: string diff --git a/config/install/field.field.node.ill_institution_request.field_ill_request_type.yml b/config/install/field.field.node.ill_institution_request.field_ill_request_type.yml new file mode 100644 index 0000000..8ff5dba --- /dev/null +++ b/config/install/field.field.node.ill_institution_request.field_ill_request_type.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_ill_request_type + - node.type.ill_institution_request + enforced: + module: + - ill_corporate_forms +id: node.ill_institution_request.field_ill_request_type +field_name: field_ill_request_type +entity_type: node +bundle: ill_institution_request +label: 'I am requesting a:' +description: '' +required: true +translatable: false +default_value: {} +default_value_callback: '' +settings: {} +field_type: list_string diff --git a/config/install/field.field.node.ill_institution_request.field_ill_system_request_number.yml b/config/install/field.field.node.ill_institution_request.field_ill_system_request_number.yml new file mode 100644 index 0000000..9aad0c5 --- /dev/null +++ b/config/install/field.field.node.ill_institution_request.field_ill_system_request_number.yml @@ -0,0 +1,21 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.node.field_ill_system_request_number + - node.type.ill_institution_request + enforced: + module: + - ill_corporate_forms +id: node.ill_institution_request.field_ill_system_request_number +field_name: field_ill_system_request_number +entity_type: node +bundle: ill_institution_request +label: 'Your System Request Number' +description: '' +required: false +translatable: false +default_value: {} +default_value_callback: '' +settings: {} +field_type: string diff --git a/config/install/field.storage.node.field_ill_item_title.yml b/config/install/field.storage.node.field_ill_item_title.yml new file mode 100644 index 0000000..0563bd7 --- /dev/null +++ b/config/install/field.storage.node.field_ill_item_title.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + module: + - node + enforced: + module: + - ill_corporate_forms +id: node.field_ill_item_title +field_name: field_ill_item_title +entity_type: node +type: string +settings: + max_length: 255 + is_ascii: false + case_sensitive: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: {} +persist_with_no_fields: false +custom_storage: false diff --git a/config/install/field.storage.node.field_ill_request_type.yml b/config/install/field.storage.node.field_ill_request_type.yml new file mode 100644 index 0000000..f4fa820 --- /dev/null +++ b/config/install/field.storage.node.field_ill_request_type.yml @@ -0,0 +1,26 @@ +langcode: en +status: true +dependencies: + module: + - node + - options + enforced: + module: + - ill_corporate_forms +id: node.field_ill_request_type +field_name: field_ill_request_type +entity_type: node +type: list_string +settings: + allowed_values: + - value: loan + label: Loan + - value: copy + label: Copy +module: options +locked: false +cardinality: 1 +translatable: true +indexes: {} +persist_with_no_fields: false +custom_storage: false diff --git a/config/install/field.storage.node.field_ill_system_request_number.yml b/config/install/field.storage.node.field_ill_system_request_number.yml new file mode 100644 index 0000000..ddb6fa3 --- /dev/null +++ b/config/install/field.storage.node.field_ill_system_request_number.yml @@ -0,0 +1,23 @@ +langcode: en +status: true +dependencies: + module: + - node + enforced: + module: + - ill_corporate_forms +id: node.field_ill_system_request_number +field_name: field_ill_system_request_number +entity_type: node +type: string +settings: + max_length: 255 + is_ascii: false + case_sensitive: false +module: core +locked: false +cardinality: 1 +translatable: true +indexes: {} +persist_with_no_fields: false +custom_storage: false diff --git a/config/install/views.view.ill_institution_requests.yml b/config/install/views.view.ill_institution_requests.yml index 423cd67..038d5ca 100644 --- a/config/install/views.view.ill_institution_requests.yml +++ b/config/install/views.view.ill_institution_requests.yml @@ -2,6 +2,9 @@ langcode: en status: true dependencies: config: + - field.storage.node.field_ill_article_title + - field.storage.node.field_ill_chapter_title + - field.storage.node.field_ill_item_title - field.storage.node.field_ill_email - field.storage.node.field_ill_item_type - field.storage.node.field_ill_partner_organization @@ -41,7 +44,7 @@ display: entity_field: title plugin_id: field label: Title - exclude: false + exclude: true alter: alter_text: false text: '' @@ -220,6 +223,69 @@ display: multi_type: separator separator: ', ' field_api_classes: false + field_ill_item_title: + id: field_ill_item_title + table: node__field_ill_item_title + field: field_ill_item_title + relationship: none + group_type: group + admin_label: '' + plugin_id: field + label: 'Item Title' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: {} + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false created: id: created table: node_field_data @@ -412,6 +478,183 @@ display: multi_type: separator separator: ', ' field_api_classes: false + field_ill_article_title: + id: field_ill_article_title + table: node__field_ill_article_title + field: field_ill_article_title + relationship: none + group_type: group + admin_label: '' + plugin_id: field + label: 'Article Title' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: {} + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + field_ill_chapter_title: + id: field_ill_chapter_title + table: node__field_ill_chapter_title + field: field_ill_chapter_title + relationship: none + group_type: group + admin_label: '' + plugin_id: field + label: 'Chapter Title' + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: string + settings: + link_to_entity: false + group_column: value + group_columns: {} + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + view_node: + id: view_node + table: node + field: view_node + relationship: none + group_type: group + admin_label: '' + entity_type: node + plugin_id: node_link + label: Operations + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + text: View pager: type: full options: @@ -652,9 +895,13 @@ display: title: title field_ill_partner_organization: field_ill_partner_organization field_ill_item_type: field_ill_item_type + field_ill_item_title: field_ill_item_title created: created field_ill_email: field_ill_email field_ill_contact_phone: field_ill_contact_phone + field_ill_article_title: field_ill_article_title + field_ill_chapter_title: field_ill_chapter_title + view_node: view_node default: created info: title: @@ -678,6 +925,13 @@ display: separator: '' empty_column: false responsive: '' + field_ill_item_title: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' created: sortable: true default_sort_order: desc @@ -699,6 +953,27 @@ display: separator: '' empty_column: false responsive: '' + field_ill_article_title: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + field_ill_chapter_title: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + view_node: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' override: true sticky: false summary: '' diff --git a/ill_corporate_forms.module b/ill_corporate_forms.module index f62a482..1b6ca6c 100644 --- a/ill_corporate_forms.module +++ b/ill_corporate_forms.module @@ -14,6 +14,7 @@ function ill_corporate_forms_form_node_ill_institution_request_form_alter(array _ill_corporate_forms_add_item_type_states($form); $form['#validate'][] = '_ill_corporate_forms_validate_partner_email'; $form['#validate'][] = '_ill_corporate_forms_validate_institution_code'; + $form['#validate'][] = '_ill_corporate_forms_validate_request_emails'; // Hide the title field; presave hook will populate it. $form['title']['#access'] = FALSE; @@ -26,11 +27,28 @@ function ill_corporate_forms_form_node_ill_institution_request_edit_form_alter(a _ill_corporate_forms_add_item_type_states($form); $form['#validate'][] = '_ill_corporate_forms_validate_partner_email'; $form['#validate'][] = '_ill_corporate_forms_validate_institution_code'; + $form['#validate'][] = '_ill_corporate_forms_validate_request_emails'; // Hide the title field; presave hook will populate it. $form['title']['#access'] = FALSE; } +/** + * Implements hook_form_FORM_ID_alter() for the ill_institution node form. + */ +function ill_corporate_forms_form_node_ill_institution_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void { + $form['#validate'][] = '_ill_corporate_forms_validate_institution_emails'; + $form['#validate'][] = '_ill_corporate_forms_validate_institution_phone'; +} + +/** + * Implements hook_form_FORM_ID_alter() for the ill_institution edit form. + */ +function ill_corporate_forms_form_node_ill_institution_edit_form_alter(array &$form, FormStateInterface $form_state, string $form_id): void { + $form['#validate'][] = '_ill_corporate_forms_validate_institution_emails'; + $form['#validate'][] = '_ill_corporate_forms_validate_institution_phone'; +} + /** * Adds #states for item-type conditional fields on the request form. * @@ -42,6 +60,7 @@ function _ill_corporate_forms_add_item_type_states(array &$form): void { // Book/Video/Thesis fields: visible when item_type is "book" OR "book_chapter". $book_fields = [ + 'field_ill_item_title', 'field_ill_author_editor', 'field_ill_isbn', 'field_ill_publication_date', @@ -201,3 +220,67 @@ function _ill_corporate_forms_validate_partner_email(array &$form, FormStateInte } } +/** + * Extracts a string value from a form state field value. + * + * @param mixed $field_value + * The raw value from $form_state->getValue(). + * + * @return string + * The extracted string value, or empty string if not found. + */ +function _ill_corporate_forms_extract_field_value($field_value): string { + if (is_array($field_value) && isset($field_value[0]['value'])) { + return (string) $field_value[0]['value']; + } + if (is_string($field_value)) { + return $field_value; + } + return ''; +} + +/** + * Validates email format for the ill_institution_request form. + */ +function _ill_corporate_forms_validate_request_emails(array &$form, FormStateInterface $form_state): void { + $email = _ill_corporate_forms_extract_field_value($form_state->getValue('field_ill_req_email')); + if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) { + $form_state->setErrorByName('field_ill_req_email', + t('The email address "@email" is not valid. Please enter a valid email address (e.g., name@example.com).', ['@email' => $email])); + } +} + +/** + * Validates email format for the ill_institution form. + */ +function _ill_corporate_forms_validate_institution_emails(array &$form, FormStateInterface $form_state): void { + $fields = [ + 'field_ill_email' => 'Email Address', + 'field_ill_contact_email' => 'Contact Email Address', + ]; + + foreach ($fields as $field_name => $label) { + $email = _ill_corporate_forms_extract_field_value($form_state->getValue($field_name)); + if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) { + $form_state->setErrorByName($field_name, + t('The @label "@email" is not valid. Please enter a valid email address (e.g., name@example.com).', [ + '@label' => $label, + '@email' => $email, + ])); + } + } +} + +/** + * Validates phone number format for the ill_institution form. + * + * Requires the format ddd-ddd-dddd (e.g., 555-123-4567). + */ +function _ill_corporate_forms_validate_institution_phone(array &$form, FormStateInterface $form_state): void { + $phone = _ill_corporate_forms_extract_field_value($form_state->getValue('field_ill_contact_phone')); + if (!empty($phone) && !preg_match('/^\d{3}-\d{3}-\d{4}$/', $phone)) { + $form_state->setErrorByName('field_ill_contact_phone', + t('The phone number "@phone" is not in the correct format. Please enter the phone number as ddd-ddd-dddd (e.g., 555-123-4567).', ['@phone' => $phone])); + } +} +