department-of-veterans-affairs / va.gov-cms

Editor-centered management for Veteran-centered content.
https://prod.cms.va.gov
GNU General Public License v2.0
98 stars 68 forks source link

[SPIKE] Discovery for epic text-field migration. #14995

Closed ndouglas closed 1 year ago

ndouglas commented 1 year ago

Description

From Tim's issue:

When text is translated from English into other languages, it often becomes longer than the English. We need to allow text to get longer for other languages.

We also need to sometimes enforce character limits on text, for a variety of reasons. In general, character limits can be enforced at the form level and/or at the database level. However, the CMS stores translated versions of text in the same location as its English.

Therefore, we cannot enforce the limits at the database/field structure level. We need to allow for arbitrary text length (text_long), and to enforce character limits at the form. Additionally, these form widgets should not enforce length limits on translations.

We also want to keep the field name as-is, so that any code that references that field - CMS or content-build - does not need to be modified, if possible.

Tim completed his proof-of-concept, but I am not Tim and therefore need to acquaint myself with this work. In addition, I have some questions that need to be answered:

Notes

Context

Acceptance Criteria

timcosgrove commented 1 year ago

How many fields are actually affected, and which ones?

This is the question that should be reviewed first. It can be looked at at the field storage level; field instances are derived from field storage config and the updates can/should happen together. The code here handles this though it should be reviewed: https://github.com/department-of-veterans-affairs/va.gov-cms/pull/14028

The field types that should be updated are string and text. There is only one instance of text in the entire CMS; this should almost certainly be converted to string_long during this process.

Some percentage of the string field instances contain machine_names; these should not be updated.

How many content types are actually affected, and which ones? How many nodes are actually affected? How many other entities might be affected?

This will only be known based on gathering the set of field storages that need updated; see above.

What is the most reliable way of performing this process? How can this process be implemented most safely? How can the correctness and safety of the process be verified?

https://github.com/department-of-veterans-affairs/va.gov-cms/pull/14028 is an implementation. The backup tables are not dropped at the end of the process, which would allow for confirmation by comparing the tables. The table data itself should not change between the two versions of the tables, and so they can in theory be checked against (hashing table dumps might be the quickest/easiest).

The implementation in the PR is not the only way, but it is a way.

How does this interoperate with revisions?

Revision tables are handled by the PR code, in addition to the primary field table.

How does this interoperate with cloned nodes?

Shouldn't matter; a cloned node is a new node, unless I misunderstand.

How does this interoperate with centralized content?

Unknown; worth looking at. At the same time, a field is a field is a field. Centralized content shouldn't matter here. The only thing that is really changing here is a) the text limit is removed, and b) the field form widget is changed.

How can we phase rollout in such a way that this can be performed safely and reliably as part of e.g. DB updates?

Part of the planning process; that said, the POC showed that the updates did not take particularly long. Depending on the number of fields that need updated, this might be staged over ~5-10 deploys.

What can we learn from this for future migrations?

To live in a shack by the river and eat mud for fun.

In seriousness, we (being CMS Team) probably want to look at what kinds of fields we want to allow for use, and to set up governance over what field types get used for what purposes. The cases where we would use a field with a database-enforced character limit are exceedingly rare.

What can we learn from this for our work in general?

To live in a shack by the river and sculpt mud for fun.

Can the core migration logic exist in a Drupal class? Or is that unsafe? What is and is not available during database updates? During deploy mode?

I don't have useful knowledge about this.

timcosgrove commented 1 year ago

Text field: only one. https://prod.cms.va.gov/admin/reports/content-model/fields?field_name=&field_type=text&entity_type=&bundle=&label=&order=field_type&sort=asc

String fields: many: https://prod.cms.va.gov/admin/reports/content-model/fields?field_name=&field_type=string&entity_type=&bundle=&label=&order=field_type&sort=asc

String fields sorted by translatability; you only want to update string fields https://prod.cms.va.gov/admin/reports/content-model/fields?field_name=&field_type=string&entity_type=&bundle=&label=&order=translatable&sort=desc

timcosgrove commented 1 year ago

Current plans for FY2024 for translation priorities: https://github.com/department-of-veterans-affairs/va.gov-team/blob/master/teams/vsa/teams/sitewide-content/translation-work/State%20Department%20translation%20work/FY2024%20translation%20planning.md

ndouglas commented 1 year ago

The Content Model Fields view didn't really the work the way I wanted it to, and I wasn't sure I understood what was happening under the hood, so I wrote a Bash script to generate the information I needed from the raw config YAML.

#!/bin/bash

declare -A translatable_fields_by_entity_type
declare -A non_translatable_fields_by_entity_type

config_dir="./config/sync"

for file in $(find "${config_dir}" -name 'field.storage.*.yml'); do
  field_type=$(yq e '.type' "${file}")

  if [ "${field_type}" == "text" ] || [ "${field_type}" == "string" ]; then
    filename="$(basename -- "${file}" ".yml")"
    entity_type="${filename#field.storage.}"
    entity_type="${entity_type%%.*}"
    field_name="${filename##*.}"

    translatable="false"

    for instance_file in $(find "${config_dir}" -name "field.field.${entity_type}.*.${field_name}.yml"); do
      instance_translatable=$(yq e '.translatable' "${instance_file}")

      if [ "$instance_translatable" == "true" ]; then
        translatable="true"
        break
      fi
    done

    if [ "$translatable" == "true" ]; then
      translatable_fields_by_entity_type[$entity_type]+="$field_name "
    else
      non_translatable_fields_by_entity_type[$entity_type]+="$field_name "
    fi
  fi
done

for entity_type in "${!translatable_fields_by_entity_type[@]}"; do
  echo "Entity type: $entity_type"
  echo "Translatable Fields:"
  for field in ${translatable_fields_by_entity_type[$entity_type]}; do
    echo "  - $field"
  done
  echo ""
done

for entity_type in "${!non_translatable_fields_by_entity_type[@]}"; do
  echo "Entity type: $entity_type"
  echo "Non-Translatable Fields:"
  for field in ${non_translatable_fields_by_entity_type[$entity_type]}; do
    echo "  - $field"
  done
  echo ""
done

This yielded the following list:

Entity type: paragraph
Translatable Fields:
  - field_phone_label
  - field_alert_heading
  - field_phone_number
  - field_text_expander
  - field_error_message
  - field_section_header
  - field_question
  - field_email_label
  - field_button_label
  - field_phone_extension
  - field_loading_message
  - field_short_phrase_with_a_number
  - field_title
  - field_link_summary

Entity type: node
Translatable Fields:
  - field_teaser_text
  - field_description
  - field_home_page_hub_label

Entity type: message
Translatable Fields:
  - field_subject
  - field_editor_username

Entity type: paragraph
Non-Translatable Fields:
  - field_widget_type
  - field_wing_floor_or_room_number
  - field_additional_hours_info
  - field_cc_documentor_title
  - field_checklist_items
  - field_magichead_heading
  - field_clinic_name
  - field_building_name_number
  - field_header

Entity type: node
Non-Translatable Fields:
  - field_name_first
  - field_va_form_title
  - field_office_id
  - field_geographical_identifier
  - field_vamc_system_official_name
  - field_event_cost
  - field_non_va_official_name
  - field_last_name
  - field_official_name
  - field_applied_to
  - field_hero_blurb
  - field_govdelivery_id_news
  - field_other_va_locations
  - field_clp_video_panel_header
  - field_govdelivery_id_emerg
  - field_facility_locator_api_id
  - field_clp_what_you_can_do_header
  - field_va_form_name
  - field_clp_resources_header
  - field_clp_spotlight_header
  - field_location_humanreadable
  - field_clp_events_header
  - field_target_paths
  - field_suffix
  - field_clp_stories_header
  - field_va_form_number

Entity type: message
Non-Translatable Fields:
  - field_target_node_title

Entity type: media
Non-Translatable Fields:
  - field_mime_type

Entity type: block_content
Non-Translatable Fields:
  - field_alert_title
  - field_promo_headline
  - field_title
  - field_primary_cta_button_text

Entity type: menu_link_content
Non-Translatable Fields:
  - field_link_summary
  - field_label

Entity type: sitewide_alert
Non-Translatable Fields:
  - field_alert_title

Entity type: taxonomy_term
Non-Translatable Fields:
  - field_description
  - field_vba_com_conditions
  - field_status_id
  - field_vet_center_friendly_name
  - field_va_benefit_api_id
  - field_cms_option_label
  - field_health_service_api_id
  - field_vba_friendly_name
  - field_vet_center_com_conditions
  - field_va_benefit_plain_name
  - field_topic_id
  - field_commonly_treated_condition
  - field_also_known_as

As far as I can tell, this matches the data presented by the Content Model Fields view but in a form that I don't have to mess with as much.

Next, I'll go through and manually prune the fields that I don't believe would be appropriate to migrate.

ndouglas commented 1 year ago

The items I've removed, and the reasons why. The burden of proof is on the field to be obviously incapable of realistically exceeding the expressed limits.

Entity type: paragraph
Translatable Fields:
  - ~field_phone_number~: Numeric.
  - ~field_phone_extension~: Numeric.

Entity type: message
Translatable Fields:
  - ~field_subject~: Outdated content only.
  - ~field_editor_username~: Outdated content only.

Entity type: paragraph
Non-Translatable Fields:
  - ~field_widget_type~: Machine name-ish.
  - ~field_wing_floor_or_room_number~: Numeric.

Entity type: node
Non-Translatable Fields:
  - ~field_office_id~: ID.
  - ~field_govdelivery_id_news~: ID.
  - ~field_other_va_locations~: ID.
  - ~field_govdelivery_id_emerg~: ID.
  - ~field_facility_locator_api_id~: ID.
  - ~field_target_paths~: Pretty mechanical.
  - ~field_va_form_number~: ID.

Entity type: message
Non-Translatable Fields:
  - ~field_target_node_title~: Outdated content only, not relevant here.

Entity type: media
Non-Translatable Fields:
  - ~field_mime_type~: Mechanical.

Entity type: sitewide_alert
Non-Translatable Fields:
  -~ field_alert_title~: Not relevant to content release.

Entity type: taxonomy_term
Non-Translatable Fields:
  - ~field_status_id~: ID.
  - ~field_va_benefit_api_id~: ID.
  - ~field_health_service_api_id~: ID.
  - ~field_topic_id~: ID.

So here are the fields that we should deal with:

Entity type: paragraph
Translatable Fields:
  - field_phone_label
  - field_alert_heading
  - field_text_expander
  - field_error_message
  - field_section_header
  - field_question
  - field_email_label
  - field_button_label
  - field_loading_message
  - field_short_phrase_with_a_number
  - field_title
  - field_link_summary

Entity type: node
Translatable Fields:
  - field_teaser_text
  - field_description
  - field_home_page_hub_label

Entity type: paragraph
Non-Translatable Fields:
  - field_additional_hours_info
  - field_cc_documentor_title
  - field_checklist_items
  - field_magichead_heading
  - field_clinic_name
  - field_building_name_number
  - field_header

Entity type: node
Non-Translatable Fields:
  - field_name_first
  - field_va_form_title
  - field_geographical_identifier
  - field_vamc_system_official_name
  - field_event_cost
  - field_non_va_official_name
  - field_last_name
  - field_official_name
  - field_applied_to
  - field_hero_blurb
  - field_clp_video_panel_header
  - field_clp_what_you_can_do_header
  - field_va_form_name
  - field_clp_resources_header
  - field_clp_spotlight_header
  - field_location_humanreadable
  - field_clp_events_header
  - field_suffix
  - field_clp_stories_header

Entity type: block_content
Non-Translatable Fields:
  - field_alert_title
  - field_promo_headline
  - field_title
  - field_primary_cta_button_text

Entity type: menu_link_content
Non-Translatable Fields:
  - field_link_summary
  - field_label

Entity type: taxonomy_term
Non-Translatable Fields:
  - field_description
  - field_vba_com_conditions
  - field_vet_center_friendly_name
  - field_cms_option_label
  - field_vba_friendly_name
  - field_vet_center_com_conditions
  - field_va_benefit_plain_name
  - field_commonly_treated_condition
  - field_also_known_as
ndouglas commented 1 year ago

So I wrote this script to tease out which content types use paragraphs whose fields will be affected:

#!/bin/bash

target_fields=(
  field_phone_label
  field_alert_heading
  field_text_expander
  field_error_message
  field_section_header
  field_question
  field_email_label
  field_button_label
  field_loading_message
  field_short_phrase_with_a_number
  field_title
  field_link_summary
)

declare -A content_types_by_paragraph

config_dir="./config/sync"

for file in $(find "${config_dir}" -name 'field.field.node.*.yml'); do
  field_type=$(yq e '.field_type' "${file}")
  if [ "${field_type}" != "entity_reference_revisions" ]; then
    continue
  fi

  filename="$(basename -- "${file}" ".yml")"
  content_type="${filename#field.field.node.}"
  content_type="${content_type%%.*}"
  paragraph_types=$(yq e '.settings.handler_settings.target_bundles' "${file}")

  for paragraph_type in $paragraph_types; do
    for target_field in "${target_fields[@]}"; do
      if [ -f "${config_dir}/field.field.paragraph.${paragraph_type}.${target_field}.yml" ]; then
        content_types_by_paragraph[$content_type]=true
      fi
    done
  done

done

echo "Content types using target fields in paragraphs:"
for content_type in "${!content_types_by_paragraph[@]}"; do
  echo "  - $content_type"
done

For translatable fields, this works out to:

Content types using target fields in paragraphs:
  - health_care_local_health_service
  - q_a
  - support_resources_detail_page
  - step_by_step
  - media_list_videos
  - media_list_images
  - faq_multiple_q_a
  - vet_center
  - health_care_region_page
  - health_care_region_detail_page
  - va_form
  - health_services_listing
  - checklist
  - health_care_local_facility
  - landing_page
  - page
  - basic_landing_page
  - documentation_page
  - campaign_landing_page

For non-translatable fields, this works out to:

Content types using target fields in paragraphs:
  - health_care_local_health_service
  - vet_center
  - vha_facility_nonclinical_service

So the content types that will be affected indirectly via modifications to fields on paragraphs should be:

  - health_care_local_health_service
  - q_a
  - support_resources_detail_page
  - step_by_step
  - media_list_videos
  - media_list_images
  - faq_multiple_q_a
  - vet_center
  - health_care_region_page
  - health_care_region_detail_page
  - va_form
  - health_services_listing
  - checklist
  - health_care_local_facility
  - landing_page
  - page
  - basic_landing_page
  - documentation_page
  - campaign_landing_page
  - health_care_local_health_service
  - vha_facility_nonclinical_service
ndouglas commented 1 year ago

To identify the nodes using targeted fields directly, I wrote this script:

#!/bin/bash

config_dir="./config/sync"

target_fields=(
  field_teaser_text
  field_description
  field_home_page_hub_label
)

declare -A content_types_by_field

for target_field in ${target_fields[@]}; do
  for file in $(find "${config_dir}" -name "field.field.node.*.$target_field.yml"); do
    filename="$(basename -- "${file}" ".yml")"
    bundle="${filename#field.field.node.}"
    bundle="${bundle%%.*}"
    content_types_by_field[$bundle]=true
  done
done

echo "Content types using target fields:"
for content_type in "${!content_types_by_field[@]}"; do
  echo "  - $content_type"
done

This yielded the following content types for the translatable fields:

Content types using target fields:
  - event
  - leadership_listing
  - press_releases_listing
  - health_care_region_page
  - publication_listing
  - health_care_region_detail_page
  - health_services_listing
  - health_care_local_facility
  - landing_page
  - person_profile
  - page
  - event_listing
  - basic_landing_page
  - office
  - outreach_asset
  - locations_listing
  - story_listing

and the following content types for non-translatable fields:

Content types using target fields:
  - event
  - vba_facility
  - vet_center
  - health_care_region_page
  - centralized_content
  - va_form
  - vet_center_cap
  - person_profile
  - campaign_landing_page

So the content types that will be affected directly will be:

  - event
  - leadership_listing
  - press_releases_listing
  - health_care_region_page
  - publication_listing
  - health_care_region_detail_page
  - health_services_listing
  - health_care_local_facility
  - landing_page
  - person_profile
  - page
  - event_listing
  - basic_landing_page
  - office
  - outreach_asset
  - locations_listing
  - story_listing
  - vba_facility
  - vet_center
  - centralized_content
  - va_form
  - vet_center_cap
  - campaign_landing_page
ndouglas commented 1 year ago

I also wanted to address the paragraphs that use block_content and the nodes that use block_content via those paragraphs. This is where things started getting boring and annoying, and the script ran long enough that I wanted some logging in there to tell me what was happening and where things were going wrong.

#!/bin/bash

target_fields=(
  field_alert_title
  field_promo_headline
  field_title
  field_primary_cta_button_text
)

declare -A block_content_bundles
declare -A paragraph_bundles_by_block_content_bundle
declare -A paragraph_bundles_by_paragraph_bundle
declare -A content_types_by_block_content_bundle
declare -A content_types_by_paragraph_bundle

config_dir="./config/sync"

for target_field in ${target_fields[@]}; do
  >&2 echo "Looking for field ${target_field}"

  for file in $(find "${config_dir}" -name "field.field.block_content.*.${target_field}.yml"); do
    filename="$(basename -- "${file}" ".yml")"
    bundle="${filename#field.field.block_content.}"
    bundle="${bundle%%.*}"
    block_content_bundles[$bundle]=true
    >&2 echo "  Found block_content bundle ${bundle}"
  done
done

>&2 echo "Looking for paragraph bundles that use block_content bundles"
for file in $(find "${config_dir}" -name "field.field.paragraph.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference" ] || [ "${handler}" != "default:block_content" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.paragraph.}"
  bundle="${bundle%%.*}"
  >&2 echo "  Checking paragraph bundle ${bundle}"
  for block_content_bundle in "${!block_content_bundles[@]}"; do
    >&2 echo "    Looking for block_content bundle ${block_content_bundle}"
    paragraph_bundles_by_block_content_bundle[$bundle]=true
    >&2 echo "      Found paragraph bundle ${bundle}"
  done
done

>&2 echo "Looking for paragraph bundles that use paragraph bundles that use block_content bundles"
for file in $(find "${config_dir}" -name "field.field.paragraph.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference_revisions" ] || [ "${handler}" != "default:paragraph" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.paragraph.}"
  bundle="${bundle%%.*}"
  paragraph_types=$(yq e '.settings.handler_settings.target_bundles' "${file}")
  >&2 echo "  Checking paragraph bundle ${bundle}"
  for paragraph_bundle in "${!paragraph_bundles_by_block_content_bundle[@]}"; do
    >&2 echo "    Looking for paragraph bundle ${paragraph_bundle}"
    for paragraph_type in $paragraph_types; do
      >&2 echo "      Checking ${paragraph_bundle} against ${paragraph_type}"
      if [ "${paragraph_bundle}" == "${paragraph_type}" ]; then
        paragraph_bundles_by_paragraph_bundle[$bundle]=true
        >&2 echo "        Found paragraph bundle ${bundle}"
        continue 2
      fi
    done
  done
done

>&2 echo "Looking for content types that use block_content bundles"
for file in $(find "${config_dir}" -name "field.field.node.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference" ] || [ "${handler}" != "default:block_content" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.node.}"
  bundle="${bundle%%.*}"
  >&2 echo "  Checking content type ${bundle}"
  for block_content_bundle in "${!block_content_bundles[@]}"; do
    >&2 echo "    Looking for block_content bundle ${block_content_bundle}"
    content_types_by_block_content_bundle[$bundle]=true
    >&2 echo "      Found content type ${bundle}"
  done
done

>&2 echo "Looking for content types that use paragraph bundles that use block_content bundles"
for file in $(find "${config_dir}" -name "field.field.node.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference_revisions" ] || [ "${handler}" != "default:paragraph" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.node.}"
  bundle="${bundle%%.*}"
  paragraph_types=$(yq e '.settings.handler_settings.target_bundles' "${file}")

  >&2 echo "  Checking content type ${bundle}"

  for paragraph_bundle in "${!paragraph_bundles_by_paragraph_bundle[@]}"; do
    >&2 echo "    Looking for paragraph bundle ${paragraph_bundle}"
    for paragraph_type in $paragraph_types; do
      >&2 echo "      Checking ${paragraph_bundle} against ${paragraph_type}"
      if [ "${paragraph_bundle}" == "${paragraph_type}" ]; then
        content_types_by_paragraph_bundle[$bundle]=true
        >&2 echo "        Found content type ${bundle}"
        continue 2
      fi
    done
  done

  for paragraph_bundle in "${!paragraph_bundles_by_block_content_bundle[@]}"; do
    >&2 echo "  Looking for paragraph bundle ${paragraph_bundle}"
    for paragraph_type in $paragraph_types; do
      >&2 echo "    Checking ${paragraph_bundle} against ${paragraph_type}"
      if [ "${paragraph_bundle}" == "${paragraph_type}" ]; then
        content_types_by_paragraph_bundle[$bundle]=true
        >&2 echo "      Found content type ${bundle}"
        continue 2
      fi
    done
  done

done

echo "Content types using block_content bundles via paragraphs:"
for content_type in "${!content_types_by_paragraph_bundle[@]}"; do
  echo "  - $content_type"
done

echo "Content types using block_content bundles directly:"
for content_type in "${!content_types_by_block_content_bundle[@]}"; do
  echo "  - $content_type"
done

After a bit, it produced this output:

Content types using block_content bundles via paragraphs:
  - q_a
  - support_resources_detail_page
  - step_by_step
  - media_list_videos
  - media_list_images
  - faq_multiple_q_a
  - centralized_content
  - health_care_region_detail_page
  - checklist
  - page
  - basic_landing_page
  - documentation_page
  - campaign_landing_page
Content types using block_content bundles directly:
  - health_care_region_detail_page
  - va_form
  - landing_page
  - page
  - campaign_landing_page

Or, combined:

  - q_a
  - support_resources_detail_page
  - step_by_step
  - media_list_videos
  - media_list_images
  - faq_multiple_q_a
  - centralized_content
  - health_care_region_detail_page
  - checklist
  - page
  - basic_landing_page
  - documentation_page
  - campaign_landing_page
  - va_form
  - landing_page
ndouglas commented 1 year ago

Finally, I wanted to get the entity types affected via taxonomy terms:

#!/bin/bash

target_fields=(
  field_description
  field_vba_com_conditions
  field_vet_center_friendly_name
  field_cms_option_label
  field_vba_friendly_name
  field_vet_center_com_conditions
  field_va_benefit_plain_name
  field_commonly_treated_condition
  field_also_known_as
)

declare -A taxonomy_vocabularies_by_field
declare -A paragraph_bundles_by_vocabulary
declare -A content_types_by_vocabulary
declare -A content_types_by_paragraph_bundle

config_dir="./config/sync"

>&2 echo "Looking for taxonomy vocabularies that use target fields"
for target_field in ${target_fields[@]}; do
  for file in $(find "${config_dir}" -name "field.field.taxonomy_term.*.${target_field}.yml"); do
    filename="$(basename -- "${file}" ".yml")"
    bundle="${filename#field.field.taxonomy_term.}"
    bundle="${bundle%%.*}"
    taxonomy_vocabularies_by_field[$bundle]=true
    >&2 echo "  Found taxonomy vocabulary ${bundle}"
  done
done

>&2 echo "Looking for paragraph bundles that use taxonomy vocabularies"
for file in $(find "${config_dir}" -name "field.field.paragraph.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference" ] || [ "${handler}" != "default:taxonomy_term" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.paragraph.}"
  field_name="${bundle##*.}"
  bundle="${bundle%%.*}"
  >&2 echo "  Checking paragraph bundle ${bundle}, field ${field_name}"
  for taxonomy_vocabulary in "${!taxonomy_vocabularies_by_field[@]}"; do
    >&2 echo "    Looking for taxonomy vocabulary ${taxonomy_vocabulary}"
    paragraph_bundles_by_vocabulary[$bundle]=true
    >&2 echo "      Found paragraph bundle ${bundle}"
  done
done

>&2 echo "Looking for paragraph bundles that use paragraph bundles that use taxonomy vocabularies"
for file in $(find "${config_dir}" -name "field.field.paragraph.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference_revisions" ] || [ "${handler}" != "default:paragraph" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.paragraph.}"
  bundle="${bundle%%.*}"
  paragraph_types=$(yq e '.settings.handler_settings.target_bundles[]' "${file}")
  >&2 echo "  Checking paragraph bundle ${bundle}"
  for paragraph_bundle in "${!paragraph_bundles_by_vocabulary[@]}"; do
    >&2 echo "    Looking for paragraph bundle ${paragraph_bundle}"
    for paragraph_type in $paragraph_types; do
      >&2 echo "      Checking ${paragraph_type} against ${paragraph_bundle}"
      if [ "${paragraph_bundle}" == "${paragraph_type}" ]; then
        paragraph_bundles_by_paragraph_bundle[$bundle]=true
        >&2 echo "        Found paragraph bundle ${bundle}"
        continue 2
      fi
    done
  done
done

# Determine which content types use the taxonomy vocabularies directly.
for file in $(find "${config_dir}" -name "field.field.node.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  if [ "${field_type}" != "entity_reference" ]; then
    continue
  fi

  filename="$(basename -- "${file}" ".yml")"
  content_type="${filename#field.field.node.}"
  content_type="${content_type%%.*}"
  taxonomy_vocabularies=$(yq e '.settings.handler_settings.target_bundles[]' "${file}")

  for taxonomy_vocabulary in $taxonomy_vocabularies; do
    content_types_by_vocabulary[$content_type]=true
  done

done

>&2 echo "Looking for content types that use paragraph bundles that use taxonomy vocabularies"
for file in $(find "${config_dir}" -name "field.field.node.*.yml"); do
  field_type=$(yq e '.field_type' "${file}")
  handler=$(yq e '.settings.handler' "${file}")
  if [ "${field_type}" != "entity_reference_revisions" ] || [ "${handler}" != "default:paragraph" ]; then
    continue
  fi
  filename="$(basename -- "${file}" ".yml")"
  bundle="${filename#field.field.node.}"
  bundle="${bundle%%.*}"
  paragraph_types=$(yq e '.settings.handler_settings.target_bundles[]' "${file}")
  >&2 echo "  Checking content type ${bundle}"

  for paragraph_bundle in "${!paragraph_bundles_by_paragraph_bundle[@]}"; do
    >&2 echo "    Looking for paragraph bundle ${paragraph_bundle}"
    for paragraph_type in $paragraph_types; do
      >&2 echo "      Checking ${paragraph_bundle} against ${paragraph_type}"
      if [ "${paragraph_bundle}" == "${paragraph_type}" ]; then
        content_types_by_paragraph_bundle[$bundle]=true
        >&2 echo "        Found content type ${bundle}"
        continue 2
      fi
    done
  done

  for paragraph_bundle in "${!paragraph_bundles_by_vocabulary[@]}"; do
    >&2 echo "  Looking for paragraph bundle ${paragraph_bundle}"
    for paragraph_type in $paragraph_types; do
      >&2 echo "    Checking ${paragraph_bundle} against ${paragraph_type}"
      if [ "${paragraph_bundle}" == "${paragraph_type}" ]; then
        content_types_by_paragraph_bundle[$bundle]=true
        >&2 echo "      Found content type ${bundle}"
        continue 2
      fi
    done
  done

done

echo "Content types using taxonomy vocabularies via paragraphs:"
for content_type in "${!content_types_by_paragraph_bundle[@]}"; do
  echo "  - $content_type"
done

echo "Content types using taxonomy vocabularies directly:"
for content_type in "${!content_types_by_vocabulary[@]}"; do
  echo "  - $content_type"
done

which yielded:

Content types using taxonomy vocabularies via paragraphs:
  - q_a
  - support_resources_detail_page
  - step_by_step
  - media_list_videos
  - media_list_images
  - faq_multiple_q_a
  - checklist
Content types using taxonomy vocabularies directly:
  - health_care_local_health_service
  - vba_facility_service
  - q_a
  - event
  - support_resources_detail_page
  - leadership_listing
  - press_releases_listing
  - step_by_step
  - media_list_videos
  - media_list_images
  - vba_facility
  - faq_multiple_q_a
  - vet_center
  - vha_facility_nonclinical_service
  - health_care_region_page
  - regional_health_care_service_des
  - vamc_system_billing_insurance
  - centralized_content
  - vet_center_locations_list
  - publication_listing
  - health_care_region_detail_page
  - nca_facility
  - va_form
  - full_width_banner_alert
  - vamc_system_policies_page
  - vet_center_cap
  - press_release
  - vet_center_outstation
  - vamc_system_medical_records_offi
  - vet_center_facility_health_servi
  - checklist
  - health_services_listing
  - banner
  - vamc_system_register_for_care
  - vamc_operating_status_and_alerts
  - health_care_local_facility
  - landing_page
  - vet_center_mobile_vet_center
  - support_service
  - news_story
  - person_profile
  - page
  - event_listing
  - basic_landing_page
  - service_region
  - office
  - documentation_page
  - outreach_asset
  - campaign_landing_page
  - locations_listing
  - promo_banner
  - story_listing
ndouglas commented 1 year ago

It's also possible that there are other things, e.g. taxonomy vocabularies referenced by block_content referenced by paragraphs referenced by paragraphs referenced by paragraphs referenced by nodes, but I think this is probably pretty accurate. Assuming I wrote these scripts correctly, which is by no means assured.

Casual plan, which I haven't thought about too deeply, is to avoid performing this migration in update hooks and instead put the CMS into maintenance mode and perform all of the modifications live. The main reason for this is that I'm expecting to use Drupal services heavily to verify correctness, and I'm leery about the decreased consistency/coherence of the update phase. Also, I want to write tests for the code, and some commands to ease insight and development.

Tomorrow I'll work on gathering the rest of the data I wanted to gather, and stretching and extruding it into some kind of useful report.

ndouglas commented 1 year ago

Next, I wanted to get a sense of the programmatic uses of each of these fields. Where does x appear in code? Is it used in calculations in presave hooks? Is it modified or validated in some specific way? What entanglements can I expect to encounter?

So I wrote this simple script... well, it started out simple and turned into a comparative deep dive (for me, at least) into awk.

#!/bin/bash

search_dir="docroot/modules/custom"

declare -a fields=(
  field_teaser_text
  field_description
  field_home_page_hub_label
  field_name_first
  field_va_form_title
  field_geographical_identifier
  field_vamc_system_official_name
  field_event_cost
  field_non_va_official_name
  field_last_name
  field_official_name
  field_applied_to
  field_hero_blurb
  field_clp_video_panel_header
  field_clp_what_you_can_do_header
  field_va_form_name
  field_clp_resources_header
  field_clp_spotlight_header
  field_location_humanreadable
  field_clp_events_header
  field_suffix
  field_clp_stories_header
  field_phone_label
  field_alert_heading
  field_text_expander
  field_error_message
  field_section_header
  field_question
  field_email_label
  field_button_label
  field_loading_message
  field_short_phrase_with_a_number
  field_title
  field_link_summary
  field_additional_hours_info
  field_cc_documentor_title
  field_checklist_items
  field_magichead_heading
  field_clinic_name
  field_building_name_number
  field_header
  field_alert_title
  field_promo_headline
  field_title
  field_primary_cta_button_text
  field_link_summary
  field_label
  field_description
  field_vba_com_conditions
  field_vet_center_friendly_name
  field_cms_option_label
  field_vba_friendly_name
  field_vet_center_com_conditions
  field_va_benefit_plain_name
  field_commonly_treated_condition
  field_also_known_as
)

for field in "${fields[@]}"; do
  echo "------------------------------------------------------"
  echo "Searching for field: $field"
  echo "------------------------------------------------------"
  last_file=""
  grep -r -n -C 4 "$field" "$search_dir" | awk -F '[-:]' '
    {
      filename = $1;
      line_num = $2;
      separator = $3;
      rest = substr($0, length($1) + length($2) + length($3) + 4);

      if (last_file != filename) {
        print filename;
        last_file = filename;
      }
      printf "%d%s %s\n", line_num, separator, rest;
    }'
done

That yielded the following output (let's just ignore that it prunes out any dashes or semicolons in the matched text -- I can't be bothered to fix that for the sake of this):

------------------------------------------------------
Searching for field: field_teaser_text
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
63      'external' => FALSE, 
64      'menu_name' => 'home page-hub-list',
65      'weight' => $weight, 
66      'field_icon' => $node >field_title_icon->value,
67      'field_link_summary' => $node >field_teaser_text->value,
68    ]); 
69    $link >save();
70  } 
71  // Create VA Department information link as external url. 
------------------------------------------------------
Searching for field: field_description
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_benefits_burials.yml
167      plugin  default_value
168      source  lastupdate
169      default_value  1
170  field_intro_text  intro_text
171  field_description  description
172  field_plainlanguage_date 
173    plugin  format_date
174    from_format  n/j/y
175    to_format  Y-m-d

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_new_landing_pages.yml
188          '@meta_title'
189          constants/meta_title_suffix
190  revision_timestamp  lastupdate
191  field_intro_text  intro_text
192  field_description  description
193  field_promo 
194    plugin  migration_lookup
195    migration  va_promo
196    source  url

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_benefits_disability_education.yml
166      plugin  default_value
167      source  lastupdate
168      default_value  1
169  field_intro_text  intro_text
170  field_description  description
171  field_plainlanguage_date 
172    plugin  format_date
173    from_format  n/j/y
174    to_format  Y-m-d

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
40     
41      name  field_meta_title
42      label  'Meta title tag'
43     
44      name  field_description
45      label  'Meta Description'
46     
47      name  field_govdelivery_id_emerg
48      label  'GovDelivery ID for Emergency Updates email'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
115     
116      plugin  callback
117      callable  trim
118      source  field_meta_title
119  field_description 
120     
121      plugin  concat
122      source 
123          constants/metadescprefix

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_hub.yml
189          '@meta_title'
190          constants/meta_title_suffix
191  revision_timestamp  lastupdate
192  field_intro_text  intro_text
193  field_description  description
194  field_promo 
195    plugin  migration_lookup
196    migration  va_promo
197    source  url

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_new_hubs.yml
166      plugin  default_value
167      source  lastupdate
168      default_value  1
169  field_intro_text  intro_text
170  field_description  description
171  field_plainlanguage_date 
172    plugin  format_date
173    from_format  n/j/y
174    to_format  Y-m-d

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
51    'title' => 'Outreach and events', 
52    'status' => '1', 
53    'uid' => 1, 
54    'moderation_state' => 'published', 
55    'field_description' => 'The office description', 
56    'field_body' => 'The office body text.', 
57  ]); 
58  $node >save();
59  $nid = (int) $node >id();

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
73    'status' => '1', 
74    'uid' => 1, 
75    'moderation_state' => 'published', 
76    'field_intro_text' => 'Event listing intro text', 
77    'field_description' => 'Event listing description', 
78    'field_office' => [ 
79      ['target_id' => $nid], 
80    ], 
81    'path' => [ 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
102    'status' => '1', 
103    'uid' => 1, 
104    'moderation_state' => 'published', 
105    'field_intro_text' => 'Publication listing intro text', 
106    'field_description' => 'Publication listing description', 
107    'field_office' => [ 
108      ['target_id' => $nid], 
109    ], 
110    'path' => [ 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
299    'step_by_step', 
300    'support_resources_detail_page', 
301  ]; 
302  foreach ($lc_bundles as $bundle) { 
303    if ($field = FieldConfig :loadByName('node', $bundle, 'field_description')) {
304      /** @var Drupal\field\FieldConfigInterface $field */ 
305      $field >delete();
306      Drupal :logger('va_gov_backend')->log(LogLevel::INFO, 'Deleted field_description from content type "%bundle".', [
307        '%bundle' => $bundle, 
308      ]); 
309    } 
310    if ($field = FieldConfig :loadByName('node', $bundle, 'field_meta_title')) {
------------------------------------------------------
Searching for field: field_home_page_hub_label
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
57  foreach ($nids as $weight => $nid) { 
58    $node = Node :load($nid);
59    $link = MenuLinkContent :create([
60      'enabled' => TRUE, 
61      'title' => $node >field_home_page_hub_label->value,
62      'link' => ['uri' => "entity {$node->toUrl()->getInternalPath()}"],
63      'external' => FALSE, 
64      'menu_name' => 'home page-hub-list',
65      'weight' => $weight, 
------------------------------------------------------
Searching for field: field_name_first
------------------------------------------------------
------------------------------------------------------
Searching for field: field_va_form_title
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_form.yml
190    bypass  FALSE
191  field_va_form_name  FormTitle
192  field_va_form_number  displayName
193  field_va_form_row_id  rowid
194  field_va_form_title  FormTitle
195  field_va_form_type  FormType
196  # field_va_form_link_teasers 
197  field_va_form_issue_date 
198     

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_form.yml
307      field_va_form_num_pages
308      field_va_form_number
309      field_va_form_revision_date
310      field_va_form_row_id
311      field_va_form_title
312      field_va_form_url
313      new_revision
314      revision_default
315      revision_log

0 
docroot/modules/custom/va_gov_workflow/src/EventSubscriber/EntityEventSubscriber.php
202   */ 
203  protected function flagVaFormChanges(EntityInterface $entity) { 
204    if ($entity >bundle() === 'va_form') {
205      $message_fields = $this >notificationsManager->buildMessageFields($entity);
206      if ($this >flagger->flagFieldChanged('field_va_form_title', 'changed_title', $entity, "The form title of this form changed from '@old' to '@new' in the Forms DB.")) {
207        $this >notificationsManager->send('va_form_changed_title', '#va-forms', $message_fields, 'slack');
208      } 
209 
210      if ($this >flagger->flagFieldChanged(['field_va_form_url', 'uri'], 'changed_filename', $entity, "The file name (URL) of this form changed from '@old' to '@new' in the Forms DB.")) {
------------------------------------------------------
Searching for field: field_geographical_identifier
------------------------------------------------------
------------------------------------------------------
Searching for field: field_vamc_system_official_name
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
17  escape  '\'
18  header_offset  0
19  track_changes  true
20  ids 
21      field_vamc_system_official_name
22  # Define any constants that are needed to pass in as data. 
23  constants 
24    cmsmigrator_id  1317
25    visnprefix  'VISN '

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
34     
35      name  field_title
36      label  'VAMC system plain language name'
37     
38      name  field_vamc_system_official_name
39      label  'VAMC system official name'
40     
41      name  field_meta_title
42      label  'Meta title tag'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
93     
94      plugin  skip_on_empty
95      method  row
96      message  'Entity lookup for Parent VISN found nothing.'
97  field_vamc_system_official_name 
98     
99      plugin  callback
100      callable  trim
101      source  field_vamc_system_official_name
102  title 
103     
104      plugin  callback
105      callable  trim

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
108     
109      plugin  concat
110      source 
111          constants/introtextprefix
112          field_vamc_system_official_name
113          constants/introtextsuffix
114  field_meta_title 
115     
116      plugin  callback

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
120     
121      plugin  concat
122      source 
123          constants/metadescprefix
124          field_vamc_system_official_name
125          constants/metadescsuffix
126  field_govdelivery_id_emerg 
127     
128      plugin  callback
------------------------------------------------------
Searching for field: field_event_cost
------------------------------------------------------
------------------------------------------------------
Searching for field: field_non_va_official_name
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_facility_vba_db_extract.yml
161      value_key  field_facility_locator_api_id
162      entity_type  node
163      bundle_key  type
164      bundle  vba_facility
165  field_non_va_official_name 
166     
167      plugin  str_replace
168      source  non_va_location_name
169      search  'NULL'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_facility_vba_db_extract.yml
230  # Only these fields will be overwritten if the content changes in the API. 
231  overwrite_properties 
232      field_administration
233      field_non_va_location_url
234      field_non_va_official_name
235      field_office
236      field_shared_vha_location
237      changed
238      new_revision
------------------------------------------------------
Searching for field: field_last_name
------------------------------------------------------
------------------------------------------------------
Searching for field: field_official_name
------------------------------------------------------
docroot/modules/custom/va_gov_consumers/va_gov_consumers.module
215  } 
216 
217  if (in_array($form_id, _va_gov_consumers_return_vet_center_form_names())) { 
218    $form['#attached']['library'][] = 'va_gov_consumers/text_field_tooltips'; 
219    $form['field_official_name']['#disabled'] = TRUE; 
220    // If common name and title are the same, don't show both unless admin. 
221    if (!\Drupal :service('va_gov_user.user_perms')->hasAdminRole() && strcmp($form['field_official_name']['widget'][0]['value']['#default_value'], $form['title']['widget'][0]['value']['#default_value']) === 0) {
222      $form['title']['#attributes']['class'][] = 'hidden css tooltip-toggle';
223    } 
224 
225  } 

0 
docroot/modules/custom/va_gov_vamc/src/EventSubscriber/VAMCEntityEventSubscriber.php
168    $entity = $event >getEntity();
169 
170    if ($this >isFlaggableFacility($entity)) {
171      if ($entity >bundle() === 'vet_center') {
172        $this >flagger->flagFieldChanged('field_official_name', 'changed_name', $entity, "The Official name of this facility changed from '@old' to '@new'.");
173        $this >notificationsManager->sendMessageOnFieldChange('field_official_name', $entity, 'Vet Center Official Name Change:', 'vet_center_official_name_change', self::USER_CMS_HELP_DESK_NOTIFICATIONS);
174      } 
175      else { 
176        $this >flagger->flagFieldChanged('title', 'changed_name', $entity, "The title of this facility changed from '@old' to '@new'.");
177        $this >notificationsManager->sendMessageOnFieldChange('title', $entity, 'Facility title changed:', 'va_facility_title_change', self::USER_CMS_HELP_DESK_NOTIFICATIONS);

0 
docroot/modules/custom/va_gov_vet_center/src/EventSubscriber/EntityEventSubscriber.php
366   *   The node form. 
367   */ 
368  public function disableNameFieldForNonAdmins(array &$form)  void {
369    if (!$this >userPermsService->hasAdminRole()) {
370      $form['field_official_name']['#disabled'] = TRUE; 
371    } 
372  } 
373 
374  /** 

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_facility_vet_centers.yml
115    value 
116        mvc
117        os
118        cap
119  field_official_name 
120    plugin  skip_on_empty
121    method  row
122    source  name
123    message  'Skipped: Source title/name is empty, can not have a node without title.'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_facility_vet_centers.yml
269      'field_geolocation'
270      field_administration
271      field_office_hours
272      field_timezone
273      field_official_name
274      field_phone_number
275      new_revision
276      revision_default
277      revision_log

0 
docroot/modules/custom/va_gov_migrate/va_gov_migrate.module
64    return; 
65  } 
66 
67  /** @var \Drupal\node\NodeInterface $entity */ 
68  // If a Vet Center title is empty copy the value from field_official_name. 
69  if (empty($entity >getTitle())) {
70    $default_title = $entity >get('field_official_name')->value ?: '- none -';
71    $entity >setTitle($default_title);
72  } 
73} 
74 
------------------------------------------------------
Searching for field: field_applied_to
------------------------------------------------------
docroot/modules/custom/va_gov_backend/src/EventSubscriber/EntityEventSubscriber.php
213        unset($form['field_product']); 
214      } 
215      // For non admin replace applied to field with static content
216      // generated from field value and disable editing. 
217      if (!empty($form['field_applied_to']['widget'][0]['value']['#default_value'])) { 
218        $title = $this >t(':title', [':title' => $form['field_applied_to']['widget'][0]['#title']]);
219        $description = $this >t(':description', [':description' => $form['field_applied_to']['widget'][0]['value']['#default_value']]);
220        $form['field_applied_to'] = [ 
221          '#prefix' => "<h3>{$title}</h3><p class=\"cc p\">{$description}</p>",
222          '#attributes' => [ 
223            'class' => ['cc special-treatment-field'],
224          ], 
225        ]; 
226      } 
227      else { 
228        unset($form['field_applied_to']); 
229      } 
230    } 
231  } 
232 
------------------------------------------------------
Searching for field: field_hero_blurb
------------------------------------------------------
------------------------------------------------------
Searching for field: field_clp_video_panel_header
------------------------------------------------------
docroot/modules/custom/va_gov_backend/va_gov_backend.module
230      ], 
231      [ 
232        'trigger' => 'field_clp_video_panel', 
233        'toggle_fields' => [ 
234          'field_clp_video_panel_header' => [ 
235            'required' => TRUE, 
236          ], 
237        ], 
238        'toggle_paragraphs' => [ 
------------------------------------------------------
Searching for field: field_clp_what_you_can_do_header
------------------------------------------------------
------------------------------------------------------
Searching for field: field_va_form_name
------------------------------------------------------
docroot/modules/custom/va_gov_consumers/va_gov_consumers.module
126function _va_gov_consumers_modify_va_form_fields(array &$form, $form_id, FormStateInterface &$form_state) { 
127  if ($form_id === 'node_va_form_edit_form' || $form_id === 'node_va_form_form') { 
128    $node = $form_state >getformObject()->getEntity();
129    $title = "<h1>{$node >getTitle()}</h1>";
130    $form_name = $form['field_va_form_name']; 
131    // We want the form name in a different location, so remove it from here. 
132    unset($form['field_va_form_name']); 
133 
134    $form['header'] = [ 
135      '#type' => 'fieldset', 
136      '#weight' => 0, 
137      '#collapsible' => FALSE, 
138      'title' => [ 
139        '#markup' => $title . '<div class="description">This non editable page title is automatically set by the VA forms database.</div>',
140      ], 
141      'field_va_form_name' => $form_name, 
142    ]; 
143 
144    _va_gov_consumers_disable_external_content_editing($form, $form_state, 'field_va_form_number'); 
145 

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_node_form.yml
187      0  3
188      1  1
189      2  5
190    bypass  FALSE
191  field_va_form_name  FormTitle
192  field_va_form_number  displayName
193  field_va_form_row_id  rowid
194  field_va_form_title  FormTitle
195  field_va_form_type  FormType
------------------------------------------------------
Searching for field: field_clp_resources_header
------------------------------------------------------
docroot/modules/custom/va_gov_backend/va_gov_backend.module
169      ], 
170      [ 
171        'trigger' => 'field_clp_resources_panel', 
172        'toggle_fields' => [ 
173          'field_clp_resources_header' => [ 
174            'required' => TRUE, 
175          ], 
176          'field_clp_resources_intro_text' => [ 
177            'required' => TRUE, 
------------------------------------------------------
Searching for field: field_clp_spotlight_header
------------------------------------------------------
docroot/modules/custom/va_gov_backend/va_gov_backend.module
189      ], 
190      [ 
191        'trigger' => 'field_clp_spotlight_panel', 
192        'toggle_fields' => [ 
193          'field_clp_spotlight_header' => [ 
194            'required' => TRUE, 
195          ], 
196          'field_clp_spotlight_intro_text' => [ 
197            'required' => TRUE, 
------------------------------------------------------
Searching for field: field_location_humanreadable
------------------------------------------------------
------------------------------------------------------
Searching for field: field_clp_events_header
------------------------------------------------------
docroot/modules/custom/va_gov_backend/va_gov_backend.module
155    'toggle_groups' => [ 
156      [ 
157        'trigger' => 'field_clp_events_panel', 
158        'toggle_fields' => [ 
159          'field_clp_events_header' => [ 
160            'required' => TRUE, 
161          ], 
162        ], 
163        'toggle_paragraphs' => [ 
------------------------------------------------------
Searching for field: field_suffix
------------------------------------------------------
------------------------------------------------------
Searching for field: field_clp_stories_header
------------------------------------------------------
docroot/modules/custom/va_gov_backend/va_gov_backend.module
209      ], 
210      [ 
211        'trigger' => 'field_clp_stories_panel', 
212        'toggle_fields' => [ 
213          'field_clp_stories_header' => [ 
214            'required' => TRUE, 
215          ], 
216          'field_clp_stories_intro' => [ 
217            'required' => TRUE, 
------------------------------------------------------
Searching for field: field_phone_label
------------------------------------------------------
docroot/modules/custom/va_gov_post_api/src/Service/PostFacilityService.php
354      // Assemble the phones. 
355      foreach ($phones as $phone) { 
356        $assembledPhone = new \stdClass(); 
357        $assembledPhone >type = $phone->get('field_phone_number_type')->value;
358        $assembledPhone >label = $phone->get('field_phone_label')->value;
359        $assembledPhone >number = $phone->get('field_phone_number')->value;
360        $assembledPhone >extension = $phone->get('field_phone_extension')->value;
361        $assembled_phones[] = $assembledPhone; 
362      } 
------------------------------------------------------
Searching for field: field_alert_heading
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/Alert.php
91        ], Message :ERROR);
92      $alert_type = 'information'; 
93    } 
94    return [ 
95      'field_alert_heading' => $query_path >find('.usa-alert-heading')->text(),
96      'field_alert_type' => $alert_type, 
97    ]; 
98  } 
99 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/Alert.php
117   * {@inheritdoc} 
118   */ 
119  protected function paragraphContent(array $paragraph_fields) { 
120    // There are child paragraphs, so we need to explicitly count this field. 
121    return $paragraph_fields['field_alert_heading']; 
122  } 
123 
124} 
------------------------------------------------------
Searching for field: field_text_expander
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/AdditionalInformation.php
30   * {@inheritdoc} 
31   */ 
32  protected function getFieldValues(DOMQuery $query_path) { 
33    return [ 
34      'field_text_expander' => $query_path >find('.additional-info-title')->text(),
35      'field_wysiwyg' => self :toRichText($query_path->find('.additional-info-content')->html()),
36    ]; 
37  } 
38 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/ExpandableText.php
41        Message :ERROR);
42      $expander = "Show more"; 
43    } 
44    return [ 
45      'field_text_expander' => $expander, 
46      'field_wysiwyg' => self :toRichText($query_path->find('.expander-content-inner')->innerHTML()),
47    ]; 
48  } 
49 
------------------------------------------------------
Searching for field: field_error_message
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/ReactWidget.php
100        'uri' => self :toUri($link_url),
101        'title' => $link_text, 
102      ], 
103      'field_button_format' => $link_button, 
104      'field_error_message' => $error, 
105      'field_loading_message' => $loading, 
106      'field_timeout' => $timeout, 
107      'field_widget_type' => $type, 
108    ]; 

0 
docroot/modules/custom/va_gov_db/va_gov_db.install
880  return $messages; 
881} 
882 
883/** 
884 * Set field_error_message text_format value on paragraph 4102. 
885 */ 
886function va_gov_db_update_9003() { 
887 
888  \Drupal :database()
889     >update('paragraph__field_error_message')
890     >condition('entity_id', 4102)
891     >fields([
892      'field_error_message_format' => 'rich_text', 
893    ]) 
894     >execute();
895  \Drupal :logger('va_gov_db')->info('Update field_error_message to full_html');
896 
897  \Drupal :database()
898     >update('paragraph_revision__field_error_message')
899     >condition('entity_id', 4102)
900     >fields([
901      'field_error_message_format' => 'rich_text', 
902    ]) 
903     >execute();
904  \Drupal :logger('va_gov_db')->info('Update field_error_message revision to full_html');
905 
906  return 'Set field_error_message text_format value on paragraph 4102.'; 
907 
908} 
909 
910/** 
------------------------------------------------------
Searching for field: field_section_header
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/QaSection.php
108      $qp = $qp >next();
109    } 
110 
111    return [ 
112      'field_section_header' => $header, 
113      'field_section_intro' => $intro_text, 
114      'field_accordion_display' => $is_accordion, 
115    ]; 
116  } 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/QaSection.php
190  /** 
191   * {@inheritdoc} 
192   */ 
193  protected function paragraphContent(array $paragraph_fields) { 
194    return $paragraph_fields['field_section_header'] . $paragraph_fields['field_section_intro']; 
195  } 
196 
197  /** 
198   * Make sure intro text doesn't contain html tags. 
------------------------------------------------------
Searching for field: field_question
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/QASchema.php
19   */ 
20  protected function getFieldValues(DOMQuery $query_path) { 
21    $question = $query_path >find('[itemprop="name"]');
22    return [ 
23      'field_question' => $question >text(),
24    ]; 
25  } 
26 
27  /** 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/QAAccordion.php
27   */ 
28  protected function getFieldValues(DOMQuery $query_path) { 
29    $question = $query_path >children('button.usa-accordion-button');
30    return [ 
31      'field_question' => $question >text(),
32    ]; 
33  } 
34 
35  /** 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/QAUnstructured.php
76    // Used to test subsequent elements to see if they're part of the answer. 
77    self :$lastQuestionLevel = substr($query_path->tag(), 1);
78 
79    return [ 
80      'field_question' => $query_path >text(),
81    ]; 
82  } 
83 
84  /** 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/Base/QABase.php
93          $qa_section >save();
94        } 
95        ParagraphType :attachParagraph($qa_section, $entity, $parent_field);
96      } 
97      ParagraphType :attachParagraph($paragraph, $qa_section, 'field_questions');
98    } 
99  } 
100 
101  /** 
------------------------------------------------------
Searching for field: field_email_label
------------------------------------------------------
docroot/modules/custom/va_gov_post_api/src/Service/PostFacilityService.php
468    $email_contacts = []; 
469    if (!empty($field_email_contacts)) { 
470      foreach ($field_email_contacts as $field_email_contact) { 
471        $contact = new \stdClass(); 
472        $contact >email_label = $field_email_contact->get('field_email_label')->value;
473        $contact >email_address = $field_email_contact->get('field_email_address')->value;
474 
475        $email_contacts[] = $contact; 
476      } 
------------------------------------------------------
Searching for field: field_button_label
------------------------------------------------------
docroot/modules/custom/va_gov_backend/va_gov_backend.module
806    $form['field_related_information']['widget'][0]['subform']['field_link']['widget'][0]['#required'] = FALSE; 
807    // Buttons paragraph. 
808    foreach ($form['field_buttons']['widget'] as $key => $button) { 
809      if (is_numeric($key)) { 
810        $form['field_buttons']['widget'][$key]['subform']['field_button_label']['widget'][0]['#required'] = FALSE; 
811        $form['field_buttons']['widget'][$key]['subform']['field_button_link']['widget'][0]['#required'] = FALSE; 
812      } 
813    } 
814 
815    foreach ($form['field_buttons']['widget'] as $idx => $val) { 
816      if (is_numeric($idx)) { 
817        $form['field_buttons']['widget'][$idx]['subform']['field_button_label']['widget'][0]['value']['#states']['required']['input[data drupal-selector="edit-field-standalone-page-value"]'] = ['checked' => TRUE];
818        $form['field_buttons']['widget'][$idx]['subform']['field_button_link']['widget'][0]['uri']['#states']['required']['input[data drupal-selector="edit-field-standalone-page-value"]'] = ['checked' => TRUE];
819      } 
820    } 
821 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.module
826    // Mark CTA button fields as required. 
827    if (!empty($form['field_buttons'])) { 
828      foreach ($form['field_buttons']['widget'] as $idx => $val) { 
829        if (is_numeric($idx)) { 
830          $form['field_buttons']['widget'][$idx]['subform']['field_button_label']['widget'][0]['value']['#required'] = TRUE; 
831          $form['field_buttons']['widget'][$idx]['subform']['field_button_link']['widget'][0]['uri']['#required'] = TRUE; 
832        } 
833      } 
834    } 
------------------------------------------------------
Searching for field: field_loading_message
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/ReactWidget.php
101        'title' => $link_text, 
102      ], 
103      'field_button_format' => $link_button, 
104      'field_error_message' => $error, 
105      'field_loading_message' => $loading, 
106      'field_timeout' => $timeout, 
107      'field_widget_type' => $type, 
108    ]; 
109 
------------------------------------------------------
Searching for field: field_short_phrase_with_a_number
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/src/Paragraph/NumberCallout.php
50        ], Message :ERROR);
51    } 
52 
53    return [ 
54      'field_short_phrase_with_a_number' => $query_path >children('.number')->text(),
55      'field_wysiwyg' => self :toRichText($query_path->children('.description')->innerHTML()),
56    ]; 
57  } 
58 
------------------------------------------------------
Searching for field: field_title
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
62      'link' => ['uri' => "entity {$node->toUrl()->getInternalPath()}"],
63      'external' => FALSE, 
64      'menu_name' => 'home page-hub-list',
65      'weight' => $weight, 
66      'field_icon' => $node >field_title_icon->value,
67      'field_link_summary' => $node >field_teaser_text->value,
68    ]); 
69    $link >save();
70  } 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/CollapsiblePanelItem.php
53      $tables = $contents >find('table')->remove();
54      $this >tables = qp('<div id="tables">' . $tables->html() . '</div>')->find('#tables');
55    } 
56    return [ 
57      'field_title' => $query_path >children('button.usa-accordion-button')->text(),
58      'field_wysiwyg' => self :toRichText($contents->html()),
59    ]; 
60  } 
61 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/CollapsiblePanelItem.php
78  /** 
79   * {@inheritdoc} 
80   */ 
81  protected function paragraphContent(array $paragraph_fields) { 
82    return $paragraph_fields['field_title'] . $paragraph_fields['field_wysiwyg']['value']; 
83  } 
84 
85} 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/LinksList.php
40    if ($query_path >prev()->hasClass('va-nav-linkslist-heading') || $query_path->prev()->hasClass('hub-page-link-list__title')) {
41      $title_raw = !empty($query_path >prev()->text()) ? $query_path->prev()->text() : '';
42    } 
43    $title = trim($title_raw); 
44    return ['field_title' => $title]; 
45  } 
46 
47  /** 
48   * {@inheritdoc} 

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_new_landing_pages.yml
221  field_alert/target_id  alert_title
222  field_administration 
223    plugin  default_value
224    default_value  76
225  field_title_icon 
226     
227      plugin  explode
228      source  url
229      delimiter  /

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
31     
32      name  visn
33      label  visn
34     
35      name  field_title
36      label  'VAMC system plain language name'
37     
38      name  field_vamc_system_official_name
39      label  'VAMC system official name'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
102  title 
103     
104      plugin  callback
105      callable  trim
106      source  field_title
107  field_intro_text 
108     
109      plugin  concat
110      source 

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
182  field_administration 
183     
184      plugin  callback
185      callable  trim
186      source  field_title
187     
188      plugin  entity_generate
189      entity_type  taxonomy_term
190      ignore_case  true

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_hub.yml
238    source  '@root_dir'
239    map 
240      burials memorials: 2
241    default_value  1
242  field_title_icon 
243     
244      plugin  static_map
245      source  '@root_dir'
246      map 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.module
1754function va_gov_backend_preprocess_paragraph(&$variables) { 
1755  $paragraph = $variables['paragraph']; 
1756  if ($paragraph >bundle() === 'downloadable_file') {
1757    $media_entities = $paragraph >get('field_media')->referencedEntities();
1758    $title = $paragraph >get('field_title')->getValue()[0]['value'];
1759    $variables['field_media'] = []; 
1760    $link_base_class = 'downloadable file-link';
1761    foreach ($media_entities as $media_entity) { 
1762      $media_object = []; 
------------------------------------------------------
Searching for field: field_link_summary
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
63      'external' => FALSE, 
64      'menu_name' => 'home page-hub-list',
65      'weight' => $weight, 
66      'field_icon' => $node >field_title_icon->value,
67      'field_link_summary' => $node >field_teaser_text->value,
68    ]); 
69    $link >save();
70  } 
71  // Create VA Department information link as external url. 

0 
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
76    'external' => TRUE, 
77    'menu_name' => 'home page-hub-list',
78    'weight' => 12, 
79    'field_icon' => 'va dept-info',
80    'field_link_summary' => 'Learn more about the VA departments that manage our benefit and health care programs.', 
81  ]); 
82  $link >save();
83} 
84 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/LinksListItem.php
104      'field_link' => [ 
105        'uri' => self :toUri($url),
106        'title' => $title, 
107      ], 
108      'field_link_summary' => $summary, 
109    ]; 
110  } 
111 
112  /** 
113   * {@inheritdoc} 
114   */ 
115  protected function paragraphContent(array $paragraph_fields) { 
116    return $paragraph_fields['field_link']['title'] . $paragraph_fields['field_link_summary']; 
117  } 
118 
119} 
------------------------------------------------------
Searching for field: field_additional_hours_info
------------------------------------------------------
docroot/modules/custom/va_gov_post_api/src/Service/PostFacilityService.php
437          // Provide no hours. 
438          $service_location >service_hours = NULL;
439        } 
440 
441        $service_location >additional_hours_info = $location->get('field_additional_hours_info')->value;
442        $use_facility_phone = $location >get('field_use_main_facility_phone')->value;
443        $service_location >phones = $this->getPhones($use_facility_phone, $location->get('field_phone')->referencedEntities());
444        // These three fields are here for Facilities API V1+ 
445        // They will eventually be part of the CMS service location, but are 
------------------------------------------------------
Searching for field: field_cc_documentor_title
------------------------------------------------------
docroot/modules/custom/va_gov_backend/src/EventSubscriber/EntityEventSubscriber.php
150          $form['field_content_block']['widget'][$key]['#attributes']['class'] = [ 
151            'cc special-treatment-paragraph',
152            $form['field_content_block']['widget'][$key]['#paragraph_type'], 
153          ]; 
154          $title = $form['field_content_block']['widget'][$key]['subform']['field_cc_documentor_title']['widget'][0]['value']['#default_value']; 
155          $title = $this >t(':title', [':title' => $title]);
156          $description = $form['field_content_block']['widget'][$key]['subform']['field_cc_documentor_description']['widget'][0]['#default_value']; 
157          $description = $this >t(':description', [':description' => $description]);
158          $form['field_content_block']['widget'][$key]['#prefix'] = "<h3>{$title}</h3><p>{$description}</p>"; 
------------------------------------------------------
Searching for field: field_checklist_items
------------------------------------------------------
------------------------------------------------------
Searching for field: field_magichead_heading
------------------------------------------------------
------------------------------------------------------
Searching for field: field_clinic_name
------------------------------------------------------
docroot/modules/custom/va_gov_post_api/src/Service/PostFacilityService.php
419      foreach ($field_service_locations as $location) { 
420        $service_location = new \stdClass(); 
421        $field_service_location_address = $location >get('field_service_location_address')->referencedEntities();
422        $address_paragraph = reset($field_service_location_address); 
423        $service_location >office_name = $this->stringNullify($address_paragraph->get('field_clinic_name')->value);
424        $service_location >service_address = $this->getServiceAddress($address_paragraph);
425        $field_email_contacts = $location >get('field_email_contacts')->referencedEntities();
426 
427        $service_location >email_contacts = $this->getEmailContacts($field_email_contacts);
------------------------------------------------------
Searching for field: field_building_name_number
------------------------------------------------------
docroot/modules/custom/va_gov_post_api/src/Service/PostFacilityService.php
495    } 
496    // We made it this far so it must be a paragraph, so declare it. 
497    /** @var \Drupal\paragraphs\Entity\Paragraph $address_paragraph */ 
498    // Prep the parts of the address not dependent on facility. 
499    $address >building_name_number = $this->stringNullify($address_paragraph->get('field_building_name_number')->value);
500    $address >wing_floor_or_room_number = $this->stringNullify($address_paragraph->get('field_wing_floor_or_room_number')->value);
501    if ($address_paragraph >get('field_use_facility_address')->value) {
502      // Get info from the facility. 
503      $field_address = $this >facility->field_address->getValue();
------------------------------------------------------
Searching for field: field_header
------------------------------------------------------
------------------------------------------------------
Searching for field: field_alert_title
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_alert_block.yml
26      alert_type
27      alert_title
28process 
29  info  alert_title
30  field_alert_title  alert_title
31  field_alert_type  alert_type
32  moderation_state 
33    plugin  default_value
34    default_value  published
------------------------------------------------------
Searching for field: field_promo_headline
------------------------------------------------------
------------------------------------------------------
Searching for field: field_title
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
62      'link' => ['uri' => "entity {$node->toUrl()->getInternalPath()}"],
63      'external' => FALSE, 
64      'menu_name' => 'home page-hub-list',
65      'weight' => $weight, 
66      'field_icon' => $node >field_title_icon->value,
67      'field_link_summary' => $node >field_teaser_text->value,
68    ]); 
69    $link >save();
70  } 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/CollapsiblePanelItem.php
53      $tables = $contents >find('table')->remove();
54      $this >tables = qp('<div id="tables">' . $tables->html() . '</div>')->find('#tables');
55    } 
56    return [ 
57      'field_title' => $query_path >children('button.usa-accordion-button')->text(),
58      'field_wysiwyg' => self :toRichText($contents->html()),
59    ]; 
60  } 
61 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/CollapsiblePanelItem.php
78  /** 
79   * {@inheritdoc} 
80   */ 
81  protected function paragraphContent(array $paragraph_fields) { 
82    return $paragraph_fields['field_title'] . $paragraph_fields['field_wysiwyg']['value']; 
83  } 
84 
85} 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/LinksList.php
40    if ($query_path >prev()->hasClass('va-nav-linkslist-heading') || $query_path->prev()->hasClass('hub-page-link-list__title')) {
41      $title_raw = !empty($query_path >prev()->text()) ? $query_path->prev()->text() : '';
42    } 
43    $title = trim($title_raw); 
44    return ['field_title' => $title]; 
45  } 
46 
47  /** 
48   * {@inheritdoc} 

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_new_landing_pages.yml
221  field_alert/target_id  alert_title
222  field_administration 
223    plugin  default_value
224    default_value  76
225  field_title_icon 
226     
227      plugin  explode
228      source  url
229      delimiter  /

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
31     
32      name  visn
33      label  visn
34     
35      name  field_title
36      label  'VAMC system plain language name'
37     
38      name  field_vamc_system_official_name
39      label  'VAMC system official name'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
102  title 
103     
104      plugin  callback
105      callable  trim
106      source  field_title
107  field_intro_text 
108     
109      plugin  concat
110      source 

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
182  field_administration 
183     
184      plugin  callback
185      callable  trim
186      source  field_title
187     
188      plugin  entity_generate
189      entity_type  taxonomy_term
190      ignore_case  true

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_hub.yml
238    source  '@root_dir'
239    map 
240      burials memorials: 2
241    default_value  1
242  field_title_icon 
243     
244      plugin  static_map
245      source  '@root_dir'
246      map 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.module
1754function va_gov_backend_preprocess_paragraph(&$variables) { 
1755  $paragraph = $variables['paragraph']; 
1756  if ($paragraph >bundle() === 'downloadable_file') {
1757    $media_entities = $paragraph >get('field_media')->referencedEntities();
1758    $title = $paragraph >get('field_title')->getValue()[0]['value'];
1759    $variables['field_media'] = []; 
1760    $link_base_class = 'downloadable file-link';
1761    foreach ($media_entities as $media_entity) { 
1762      $media_object = []; 
------------------------------------------------------
Searching for field: field_primary_cta_button_text
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
96    'moderation_state' => 'published', 
97    'revision_log' => 'Initial creation via Drush deploy hook.', 
98    'field_administration' => ['target_id' => 1109], 
99    'field_cta_summary_text' => 'Create an account to manage your VA benefits and care in one place — anytime, from anywhere.', 
100    'field_primary_cta_button_text' => 'Create account', 
101    'field_primary_cta_button_url' => ['uri' => 'internal /<none>'],
102    'field_related_info_links' => [ 
103      'uri' => 'entity node/51915',
104      'title' => 'Learn how an account helps you', 
------------------------------------------------------
Searching for field: field_link_summary
------------------------------------------------------
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
63      'external' => FALSE, 
64      'menu_name' => 'home page-hub-list',
65      'weight' => $weight, 
66      'field_icon' => $node >field_title_icon->value,
67      'field_link_summary' => $node >field_teaser_text->value,
68    ]); 
69    $link >save();
70  } 
71  // Create VA Department information link as external url. 

0 
docroot/modules/custom/va_gov_home/va_gov_home.deploy.php
76    'external' => TRUE, 
77    'menu_name' => 'home page-hub-list',
78    'weight' => 12, 
79    'field_icon' => 'va dept-info',
80    'field_link_summary' => 'Learn more about the VA departments that manage our benefit and health care programs.', 
81  ]); 
82  $link >save();
83} 
84 

0 
docroot/modules/custom/va_gov_migrate/src/Paragraph/LinksListItem.php
104      'field_link' => [ 
105        'uri' => self :toUri($url),
106        'title' => $title, 
107      ], 
108      'field_link_summary' => $summary, 
109    ]; 
110  } 
111 
112  /** 
113   * {@inheritdoc} 
114   */ 
115  protected function paragraphContent(array $paragraph_fields) { 
116    return $paragraph_fields['field_link']['title'] . $paragraph_fields['field_link_summary']; 
117  } 
118 
119} 
------------------------------------------------------
Searching for field: field_label
------------------------------------------------------
docroot/modules/custom/va_gov_facilities/va_gov_facilities.install
21 
22  foreach ($terms as $term) { 
23    $is_vamc_service = !empty($term >get('field_service_type_of_care')->value);
24    $is_vet_center_service = !empty($term >get('field_vet_center_type_of_care')->value);
25    $field_labels = []; 
26    if ($is_vamc_service) { 
27      $term >field_show_for_vamc_facilities->value = 1;
28      $field_labels[] = '"Show for VAMC Facilties"'; 
29    } 
30    if ($is_vet_center_service) { 
31      $term >field_show_for_vet_centers->value = 1;
32      $field_labels[] = '"Show for Vet Centers"'; 
33    } 
34    if (!empty($field_labels)) { 
35      // There was a data change, so save it. 
36      _va_gov_facilities_save_term($term, $updated, $failed, $taxonomy, $field_labels); 
37    } 
38  } 
39  Drupal :logger('va_gov_facilities')->log(LogLevel::INFO, $taxonomy . ': ' . 'Successfully updated "Show for VAMC Facilties" and "Show for Vet Centers" %updated terms. Failed to update %failed terms.', [
40    '%count' => count($terms), 

0 
docroot/modules/custom/va_gov_facilities/va_gov_facilities.install
54 * @param int $failed 
55 *   Count of failures. 
56 * @param string $taxonomy 
57 *   Name of taxonomy. 
58 * @param array $field_labels 
59 *   Labels of updated fields. 
60 */ 
61function _va_gov_facilities_save_term(TermInterface &$term, &$updated, &$failed, $taxonomy, array $field_labels)  void {
62  try { 
63    $term >setNewRevision(TRUE);
64    // Setting revision as CMS migrator. 
65    // Core bug  setting the user is not reflected in term revisions.

0 
docroot/modules/custom/va_gov_facilities/va_gov_facilities.install
67    $term >setRevisionCreationTime(time());
68    $term >setChangedTime(time());
69    $term >setSyncing(TRUE);
70    $term >setValidationRequired(FALSE);
71    $labels = implode(',', $field_labels); 
72    $term >setRevisionLogMessage("CMS Migrator updated $labels checkbox(es).");
73    $term >isDefaultRevision(TRUE);
74    $saved = $term >save();
75    // Repeated save to clear out revision log.  There is an intentional bit 

0 
docroot/modules/custom/va_gov_facilities/va_gov_facilities.install
80    $term >isDefaultRevision(TRUE);
81    $saved = $term >save();
82 
83    $updated = (($saved === SAVED_NEW) || ($saved === SAVED_UPDATED)) ? ++$updated   $updated;
84    foreach ($field_labels as $field_label) { 
85      Drupal :logger('va_gov_facilities')->log(LogLevel::INFO, $taxonomy . ": " . $field_label . ' set for "%term_name".', [
86        '%term_name' => $term >label(),
87      ]); 
88    } 
89 
90  } 
91  catch (\Exception $e) { 
92    $failed++; 
93    foreach ($field_labels as $field_label) { 
94      Drupal :logger('va_gov_facilities')->log(LogLevel::ERROR, $taxonomy . ": " . $field_label . ' failed to update for "%term_name". Do it manually. Error message: %error_message.', [
95        '%term_name' => $term >label(),
96        '%error_message' => $e >getMessage(),
97      ]); 
98    } 
------------------------------------------------------
Searching for field: field_description
------------------------------------------------------
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_benefits_burials.yml
167      plugin  default_value
168      source  lastupdate
169      default_value  1
170  field_intro_text  intro_text
171  field_description  description
172  field_plainlanguage_date 
173    plugin  format_date
174    from_format  n/j/y
175    to_format  Y-m-d

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_new_landing_pages.yml
188          '@meta_title'
189          constants/meta_title_suffix
190  revision_timestamp  lastupdate
191  field_intro_text  intro_text
192  field_description  description
193  field_promo 
194    plugin  migration_lookup
195    migration  va_promo
196    source  url

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_benefits_disability_education.yml
166      plugin  default_value
167      source  lastupdate
168      default_value  1
169  field_intro_text  intro_text
170  field_description  description
171  field_plainlanguage_date 
172    plugin  format_date
173    from_format  n/j/y
174    to_format  Y-m-d

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
40     
41      name  field_meta_title
42      label  'Meta title tag'
43     
44      name  field_description
45      label  'Meta Description'
46     
47      name  field_govdelivery_id_emerg
48      label  'GovDelivery ID for Emergency Updates email'

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.health_care_region_page.yml
115     
116      plugin  callback
117      callable  trim
118      source  field_meta_title
119  field_description 
120     
121      plugin  concat
122      source 
123          constants/metadescprefix

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_hub.yml
189          '@meta_title'
190          constants/meta_title_suffix
191  revision_timestamp  lastupdate
192  field_intro_text  intro_text
193  field_description  description
194  field_promo 
195    plugin  migration_lookup
196    migration  va_promo
197    source  url

0 
docroot/modules/custom/va_gov_migrate/config/install/migrate_plus.migration.va_new_hubs.yml
166      plugin  default_value
167      source  lastupdate
168      default_value  1
169  field_intro_text  intro_text
170  field_description  description
171  field_plainlanguage_date 
172    plugin  format_date
173    from_format  n/j/y
174    to_format  Y-m-d

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
51    'title' => 'Outreach and events', 
52    'status' => '1', 
53    'uid' => 1, 
54    'moderation_state' => 'published', 
55    'field_description' => 'The office description', 
56    'field_body' => 'The office body text.', 
57  ]); 
58  $node >save();
59  $nid = (int) $node >id();

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
73    'status' => '1', 
74    'uid' => 1, 
75    'moderation_state' => 'published', 
76    'field_intro_text' => 'Event listing intro text', 
77    'field_description' => 'Event listing description', 
78    'field_office' => [ 
79      ['target_id' => $nid], 
80    ], 
81    'path' => [ 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
102    'status' => '1', 
103    'uid' => 1, 
104    'moderation_state' => 'published', 
105    'field_intro_text' => 'Publication listing intro text', 
106    'field_description' => 'Publication listing description', 
107    'field_office' => [ 
108      ['target_id' => $nid], 
109    ], 
110    'path' => [ 

0 
docroot/modules/custom/va_gov_backend/va_gov_backend.install
299    'step_by_step', 
300    'support_resources_detail_page', 
301  ]; 
302  foreach ($lc_bundles as $bundle) { 
303    if ($field = FieldConfig :loadByName('node', $bundle, 'field_description')) {
304      /** @var Drupal\field\FieldConfigInterface $field */ 
305      $field >delete();
306      Drupal :logger('va_gov_backend')->log(LogLevel::INFO, 'Deleted field_description from content type "%bundle".', [
307        '%bundle' => $bundle, 
308      ]); 
309    } 
310    if ($field = FieldConfig :loadByName('node', $bundle, 'field_meta_title')) {
------------------------------------------------------
Searching for field: field_vba_com_conditions
------------------------------------------------------
------------------------------------------------------
Searching for field: field_vet_center_friendly_name
------------------------------------------------------
docroot/modules/custom/va_gov_facilities/src/EventSubscriber/FacilitiesSubscriber.php
506      // Make the bundle available to displayServiceDescriptions.js. 
507      $form['#attached']['drupalSettings']['currentNodeBundle'] = $bundle; 
508      $fields = [ 
509        'type' => $bundle === 'vet_center' ? 'field_vet_center_type_of_care'   'field_service_type_of_care',
510        'name' => $bundle === 'vet_center' ? 'field_vet_center_friendly_name'   'field_also_known_as',
511        'conditions' => $bundle === 'vet_center' ? 'field_vet_center_com_conditions'   'field_commonly_treated_condition',
512        'description' => $bundle === 'vet_center' ? 'field_vet_center_service_descrip'   'description',
513      ]; 
514    } 
------------------------------------------------------
Searching for field: field_cms_option_label
------------------------------------------------------
------------------------------------------------------
Searching for field: field_vba_friendly_name
------------------------------------------------------
------------------------------------------------------
Searching for field: field_vet_center_com_conditions
------------------------------------------------------
docroot/modules/custom/va_gov_facilities/src/EventSubscriber/FacilitiesSubscriber.php
507      $form['#attached']['drupalSettings']['currentNodeBundle'] = $bundle; 
508      $fields = [ 
509        'type' => $bundle === 'vet_center' ? 'field_vet_center_type_of_care'   'field_service_type_of_care',
510        'name' => $bundle === 'vet_center' ? 'field_vet_center_friendly_name'   'field_also_known_as',
511        'conditions' => $bundle === 'vet_center' ? 'field_vet_center_com_conditions'   'field_commonly_treated_condition',
512        'description' => $bundle === 'vet_center' ? 'field_vet_center_service_descrip'   'description',
513      ]; 
514    } 
515    return $fields; 
------------------------------------------------------
Searching for field: field_va_benefit_plain_name
------------------------------------------------------
------------------------------------------------------
Searching for field: field_commonly_treated_condition
------------------------------------------------------
docroot/modules/custom/va_gov_facilities/src/EventSubscriber/FacilitiesSubscriber.php
507      $form['#attached']['drupalSettings']['currentNodeBundle'] = $bundle; 
508      $fields = [ 
509        'type' => $bundle === 'vet_center' ? 'field_vet_center_type_of_care'   'field_service_type_of_care',
510        'name' => $bundle === 'vet_center' ? 'field_vet_center_friendly_name'   'field_also_known_as',
511        'conditions' => $bundle === 'vet_center' ? 'field_vet_center_com_conditions'   'field_commonly_treated_condition',
512        'description' => $bundle === 'vet_center' ? 'field_vet_center_service_descrip'   'description',
513      ]; 
514    } 
515    return $fields; 
------------------------------------------------------
Searching for field: field_also_known_as
------------------------------------------------------
docroot/modules/custom/va_gov_facilities/src/EventSubscriber/FacilitiesSubscriber.php
506      // Make the bundle available to displayServiceDescriptions.js. 
507      $form['#attached']['drupalSettings']['currentNodeBundle'] = $bundle; 
508      $fields = [ 
509        'type' => $bundle === 'vet_center' ? 'field_vet_center_type_of_care'   'field_service_type_of_care',
510        'name' => $bundle === 'vet_center' ? 'field_vet_center_friendly_name'   'field_also_known_as',
511        'conditions' => $bundle === 'vet_center' ? 'field_vet_center_com_conditions'   'field_commonly_treated_condition',
512        'description' => $bundle === 'vet_center' ? 'field_vet_center_service_descrip'   'description',
513      ]; 
514    } 
ndouglas commented 1 year ago

I reviewed the above findings and added a table for the fields and their respective migration- and code-based entanglements.

Then I created a raw list of content types affected, which... I think is all of them 😂

I created the following script to count the affected nodes and revisions for each content type:

#!/bin/bash

total_nodes=0
total_revisions=0

content_types=(
  "banner"
  "basic_landing_page"
  "campaign_landing_page"
  "centralized_content"
  "checklist"
  "documentation_page"
  "event"
  "event_listing"
  "faq_multiple_q_a"
  "full_width_banner_alert"
  "health_care_local_facility"
  "health_care_local_health_service"
  "health_care_region_detail_page"
  "health_care_region_page"
  "health_services_listing"
  "landing_page"
  "leadership_listing"
  "locations_listing"
  "media_list_images"
  "media_list_videos"
  "nca_facility"
  "news_story"
  "office"
  "outreach_asset"
  "page"
  "person_profile"
  "press_release"
  "press_releases_listing"
  "promo_banner"
  "publication_listing"
  "q_a"
  "regional_health_care_service_des"
  "service_region"
  "step_by_step"
  "story_listing"
  "support_resources_detail_page"
  "support_service"
  "va_form"
  "vamc_operating_status_and_alerts"
  "vamc_system_billing_insurance"
  "vamc_system_medical_records_offi"
  "vamc_system_policies_page"
  "vamc_system_register_for_care"
  "vba_facility"
  "vba_facility_service"
  "vet_center"
  "vet_center_cap"
  "vet_center_facility_health_servi"
  "vet_center_locations_list"
  "vet_center_mobile_vet_center"
  "vet_center_outstation"
  "vha_facility_nonclinical_service"
)

for type in "${content_types[@]}"; do
  num_nodes=$(drush sql:query "SELECT COUNT(*) FROM node WHERE type=\"$type\";")
  num_revisions=$(drush sql:query "SELECT COUNT(*) FROM node_revision nr JOIN node_field_data nfd ON nr.nid = nfd.nid WHERE nfd.type=\"$type\";")
  echo "Content type: $type, Nodes: $num_nodes, Revisions: $num_revisions"
  total_nodes=$((total_nodes + num_nodes))
  total_revisions=$((total_revisions + num_revisions))
done

echo "----------------------------------"
echo "Total Nodes: $total_nodes"
echo "Total Revisions: $total_revisions"

This yielded the following output:

Content type: banner, Nodes: 9, Revisions: 75
Content type: basic_landing_page, Nodes: 6, Revisions: 61
Content type: campaign_landing_page, Nodes: 16, Revisions: 968
Content type: centralized_content, Nodes: 7, Revisions: 112
Content type: checklist, Nodes: 2, Revisions: 13
Content type: documentation_page, Nodes: 193, Revisions: 3105
Content type: event, Nodes: 6891, Revisions: 18845
Content type: event_listing, Nodes: 142, Revisions: 1020
Content type: faq_multiple_q_a, Nodes: 29, Revisions: 573
Content type: full_width_banner_alert, Nodes: 744, Revisions: 4478
Content type: health_care_local_facility, Nodes: 1400, Revisions: 337452
Content type: health_care_local_health_service, Nodes: 15058, Revisions: 54993
Content type: health_care_region_detail_page, Nodes: 6369, Revisions: 72470
Content type: health_care_region_page, Nodes: 141, Revisions: 6681
Content type: health_services_listing, Nodes: 140, Revisions: 1375
Content type: landing_page, Nodes: 18, Revisions: 546
Content type: leadership_listing, Nodes: 140, Revisions: 1965
Content type: locations_listing, Nodes: 140, Revisions: 1216
Content type: media_list_images, Nodes: 1, Revisions: 12
Content type: media_list_videos, Nodes: 2, Revisions: 7
Content type: nca_facility, Nodes: 194, Revisions: 5446
Content type: news_story, Nodes: 2817, Revisions: 12268
Content type: office, Nodes: 6, Revisions: 35
Content type: outreach_asset, Nodes: 357, Revisions: 2411
Content type: page, Nodes: 402, Revisions: 18375
Content type: person_profile, Nodes: 6227, Revisions: 24354
Content type: press_release, Nodes: 1890, Revisions: 5336
Content type: press_releases_listing, Nodes: 142, Revisions: 1115
Content type: promo_banner, Nodes: 2, Revisions: 18
Content type: publication_listing, Nodes: 1, Revisions: 12
Content type: q_a, Nodes: 269, Revisions: 2416
Content type: regional_health_care_service_des, Nodes: 6497, Revisions: 57054
Content type: service_region, Nodes: 0, Revisions: 0
Content type: step_by_step, Nodes: 14, Revisions: 329
Content type: story_listing, Nodes: 141, Revisions: 919
Content type: support_resources_detail_page, Nodes: 81, Revisions: 1823
Content type: support_service, Nodes: 18, Revisions: 123
Content type: va_form, Nodes: 744, Revisions: 9785
Content type: vamc_operating_status_and_alerts, Nodes: 140, Revisions: 2826
Content type: vamc_system_billing_insurance, Nodes: 139, Revisions: 869
Content type: vamc_system_medical_records_offi, Nodes: 139, Revisions: 393
Content type: vamc_system_policies_page, Nodes: 140, Revisions: 1231
Content type: vamc_system_register_for_care, Nodes: 139, Revisions: 370
Content type: vba_facility, Nodes: 466, Revisions: 11187
Content type: vba_facility_service, Nodes: 0, Revisions: 0
Content type: vet_center, Nodes: 300, Revisions: 25057
Content type: vet_center_cap, Nodes: 475, Revisions: 2824
Content type: vet_center_facility_health_servi, Nodes: 3719, Revisions: 23951
Content type: vet_center_locations_list, Nodes: 300, Revisions: 987
Content type: vet_center_mobile_vet_center, Nodes: 83, Revisions: 639
Content type: vet_center_outstation, Nodes: 20, Revisions: 506
Content type: vha_facility_nonclinical_service, Nodes: 598, Revisions: 1418
----------------------------------
Total Nodes: 57908
Total Revisions: 720044
ndouglas commented 1 year ago

I slightly modified the script above to yield similar results for block_content:

Bundle: alert, Entities: 98, Revisions: 766
Bundle: benefit_promo, Entities: 1, Revisions: 1
Bundle: cms_announcement, Entities: 1, Revisions: 1
Bundle: cta_with_link, Entities: 1, Revisions: 2
Bundle: news_promo, Entities: 1, Revisions: 3
Bundle: promo, Entities: 144, Revisions: 424
----------------------------------
Total Entities: 246
Total Revisions: 1197

and for taxonomy_term:

Vocabulary: administration, Terms: 570, Revisions: 1052
Vocabulary: facility_supplemental_status, Terms: 3, Revisions: 33
Vocabulary: health_care_service_taxonomy, Terms: 108, Revisions: 497
Vocabulary: va_benefits_taxonomy, Terms: 0, Revisions: 0
----------------------------------
Total Terms: 681
Total Revisions: 1582
ndouglas commented 1 year ago

Summary

Every field that stores text for translation and is potentially affected by this issue

Entity type Translatable Fields Non-Translatable Fields
node field_teaser_text
field_description
field_home_page_hub_label
field_name_first
field_va_form_title
field_geographical_identifier
field_vamc_system_official_name
field_event_cost
field_non_va_official_name
field_last_name
field_official_name
field_applied_to
field_hero_blurb
field_clp_video_panel_header
field_clp_what_you_can_do_header
field_va_form_name
field_clp_resources_header
field_clp_spotlight_header
field_location_humanreadable
field_clp_events_header
field_suffix
field_clp_stories_header
paragraph field_phone_label
field_alert_heading
field_text_expander
field_error_message
field_section_header
field_question
field_email_label
field_button_label
field_loading_message
field_short_phrase_with_a_number
field_title
field_link_summary
field_additional_hours_info
field_cc_documentor_title
field_checklist_items
field_magichead_heading
field_clinic_name
field_building_name_number
field_header
block_content field_alert_title
field_promo_headline
field_title
field_primary_cta_button_text
menu_link_content field_link_summary
field_label
taxonomy_term field_description
field_vba_com_conditions
field_vet_center_friendly_name
field_cms_option_label
field_vba_friendly_name
field_vet_center_com_conditions
field_va_benefit_plain_name
field_commonly_treated_condition
field_also_known_as

Fields and Their Migration Entanglements

Field name Entanglement
field_description va_benefits_burials
va_new_landing_pages
va_benefits_disability_education
health_care_region_page
va_hub
va_new_hubs
field_va_form_title va_node_form
field_vamc_system_official_name health_care_region_page
field_non_va_official_name va_node_facility_vba_db_extract
field_official_name va_node_facility_vet_centers
field_va_form_name va_node_form
field_title va_new_landing_pages
health_care_region_page
va_hub
va_new_hubs
field_alert_title va_alert_block

Fields and Their Code Entanglements

Field name Entanglement
field_teaser_text Used in va_gov_home_deploy_create_hub_menu_links(), which creates hub menu links.
field_home_page_hub_label Used in va_gov_home_deploy_create_hub_menu_links(), which creates hub menu links.
field_va_form_title Used in \Drupal\va_gov_workflow\EventSubscriber\EntityEventSubscriber::flagVaFormChanges(), which detects form title changes.
field_official_name Used in _va_gov_consumers_modify_facility_fields(), which modifies the display of the fields on vet center form.
Used in \Drupal\va_gov_vamc\EventSubscriber\VAMCEntityEventSubscriber::entityUpdate() to detect form title changes.
Used in \Drupal\va_gov_vet_center\EventSubscriber\EntityEventSubscriber::disableNameFieldForNonAdmins() to disable the field for non-admins.
Used in _va_gov_migrate_set_default_vet_center_title() to set a sane default title.
field_applied_to Used in \Drupal\va_gov_backend\EventSubscriber\EntityEventSubscriber::lockCentralizedContentFields(), which disables editing for non-admins.
field_clp_video_panel_header Used in _va_gov_backend_get_clp_toggles(), which toggles CLP fields.
field_va_form_name Used in _va_gov_consumers_modify_va_form_fields(), which modifies the display of the fields on VA forms.
field_clp_resources_header Used in _va_gov_backend_get_clp_toggles(), which toggles CLP fields.
field_clp_spotlight_header Used in _va_gov_backend_get_clp_toggles(), which toggles CLP fields.
field_clp_events_header Used in _va_gov_backend_get_clp_toggles(), which toggles CLP fields.
field_clp_stories_header Used in _va_gov_backend_get_clp_toggles(), which toggles CLP fields.
field_phone_label Used in \Drupal\va_gov_post_api\Service\PostFacilityService::getPhones(), which assembles phone numbers.
field_alert_heading Used in \Drupal\va_gov_migrate\Paragraph\Alert::getFieldValues() and ::paragraphContent() for migrating alert paragraphs.
field_text_expander Used in \Drupal\va_gov_migrate\Paragraph\AdditionalInformation::getFieldValues() for migrating additional information paragraphs.
Used in \Drupal\va_gov_migrate\Paragraph\ExpandableText::getFieldValues() for migrating expandable text paragraphs.
field_error_message Used in \Drupal\va_gov_migrate\Paragraph\ReactWidget::getFieldValues() for migrating react widget paragraphs.
field_section_header Used in \Drupal\va_gov_migrate\Paragraph\QaSection::getFieldValues() and ::paragraphContent() for migrating Q&A section paragraphs.
field_question Used in \Drupal\va_gov_migrate\Paragraph\QaSchema::getFieldValues() for migrating Q&A paragraphs.
Used in \Drupal\va_gov_migrate\Paragraph\QaAccordion::getFieldValues() for migrating accordions to Q&A paragraphs.
Used in \Drupal\va_gov_migrate\Paragraph\QaUnstructured::getFieldValues() for migrating Q&A paragraphs.
field_email_label Used in \Drupal\va_gov_post_api\Service\PostFacilityService::getEmailContacts(), which assembles email contacts.
field_button_label Used in _va_gov_backend_alter_standalone_page_validation(), which alters the validation for standalone page options.
field_loading_message Used in \Drupal\va_gov_migrate\Paragraph\ReactWidget::getFieldValues() for migrating react widget paragraphs.
field_short_phrase_with_a_number Used in \Drupal\va_gov_migrate\Paragraph\NumberCallout::getFieldValues() for migrating number callout paragraphs.
field_title Used in \Drupal\va_gov_migrate\Paragraph\CollapsiblePanelItem::getFieldValues() and ::paragraphContent() for migrating starred horizontal rule paragraphs.
\Drupal\va_gov_migrate\Paragraph\LinksList::getFieldValues() for migrating links list paragraphs.
Used in va_gov_backend_preprocess_paragraph() to retrieve the paragraph title.
field_link_summary Used in va_gov_home_deploy_create_hub_menu_links(), which creates hub menu links.
Used in \Drupal\va_gov_migrate\Paragraph\LinksListItem::getFieldValues() and ::paragraphContent() for migrating links list item paragraphs.
field_additional_hours_info Used in \Drupal\va_gov_post_api\Service\PostFacilityService::getServiceLocation(), which assembles service locations.
field_cc_documentor_title Used in \Drupal\va_gov_backend\EventSubscriber\EntityEventSubscriber::lockCcDocumentorParagraphs(), which locks paragraphs for non-admins.
field_clinic_name Used in \Drupal\va_gov_post_api\Service\PostFacilityService::getServiceLocations(), which assembles service locations.
field_building_name_number Used in \Drupal\va_gov_post_api\Service\PostFacilityService::getServiceAddress(), which assembles service addresses.
field_primary_cta_button_text Used in va_gov_home_deploy_create_i_cta_with_links(), which creates a new CTA with Links block for Homepage, and adds it to entityqueue.
field_link_summary Used in va_gov_home_deploy_create_hub_menu_links(), which creates hub menu links.
Used in \Drupal\va_gov_migrate\Paragraph\LinksListItem::getFieldValues() and ::paragraphContent() for migrating links list item paragraphs.
field_vet_center_friendly_name Used in \Drupal\va_gov_facilities\EventSubscriber\FacilitiesSubscriber::getProductTypeTermFields(), which builds an array of term fields predicated by product type.
field_commonly_treated_condition Used in \Drupal\va_gov_facilities\EventSubscriber\FacilitiesSubscriber::getProductTypeTermFields(), which builds an array of term fields predicated by product type.
field_also_known_as Used in \Drupal\va_gov_facilities\EventSubscriber\FacilitiesSubscriber::getProductTypeTermFields(), which builds an array of term fields predicated by product type.

Affected Content Types, Nodes, and Revisions

Content Type Nodes Revisions
banner 9 75
basic_landing_page 6 61
campaign_landing_page 16 968
centralized_content 7 112
checklist 2 13
documentation_page 193 3105
event 6891 18845
event_listing 142 1020
faq_multiple_q_a 29 573
full_width_banner_alert 744 4478
health_care_local_facility 1400 337452
health_care_local_health_service 15058 54993
health_care_region_detail_page 6369 72470
health_care_region_page 141 6681
health_services_listing 140 1375
landing_page 18 546
leadership_listing 140 1965
locations_listing 140 1216
media_list_images 1 12
media_list_videos 2 7
nca_facility 194 5446
news_story 2817 12268
office 6 35
outreach_asset 357 2411
page 402 18375
person_profile 6227 24354
press_release 1890 5336
press_releases_listing 142 1115
promo_banner 2 18
publication_listing 1 12
q_a 269 2416
regional_health_care_service_des 6497 57054
service_region 0 0
step_by_step 14 329
story_listing 141 919
support_resources_detail_page 81 1823
support_service 18 123
va_form 744 9785
vamc_operating_status_and_alerts 140 2826
vamc_system_billing_insurance 139 869
vamc_system_medical_records_offi 139 393
vamc_system_policies_page 140 1231
vamc_system_register_for_care 139 370
vba_facility 466 11187
vba_facility_service 0 0
vet_center 300 25057
vet_center_cap 475 2824
vet_center_facility_health_servi 3719 23951
vet_center_locations_list 300 987
vet_center_mobile_vet_center 83 639
vet_center_outstation 20 506
vha_facility_nonclinical_service 598 1418
Total 57908 720044

Affected block_content entities

Bundle Entities Revisions
alert 98 766
benefit_promo 1 1
cms_announcement 1 1
cta_with_link 1 2
news_promo 1 3
promo 144 424
Total 246 1197

Affected taxonomy terms

Vocabulary Terms Revisions
administration 570 1052
facility_supplemental_status 3 33
health_care_service_taxonomy 108 497
va_benefits_taxonomy 0 0
Total 681 1582

Relationship and potential impact of all changes

While this does seem to affect essentially everything directly or indirectly, I didn't find any places in the CMS code that seemed intimately dependent upon the structure and type of any given field. It's possible that these are indirect, and will only pop up in actual use. There's not much I can do to anticipate that.

The content-build relationship with this work has an extremely broad cross- section. I expect, though, that issues will be found by the content-build-gql test or the full content build.

I don't see much reason to be concerned, but I can use the data gathered to make some estimates on how much time the complete process will take. I still think it is wise to make changes individually, allowing some time between each batch. As my confidence grows in the approach, I might compound later batches.

Lessons Learned

This is ugly, and I don't like it. We shouldn't be in this predicament. Setting a limit of 255 characters on a human text field in a database is just not very forward-looking.

I'll place information about implementation in #13699.