# Field Value Tracker

## INTRODUCTION

The Field Value Tracker module provides functionality to track and update
field values between different environments. The main use case is to provide
different values for URLs, email addresses, and other environment-specific
content between production and lower environments (staging, development, etc.).

This module creates a content entity that stores four key pieces of information:
- **Mode**: How to handle the update (Replace or Overwrite)
- **Field Target**: The specific field being tracked (entity reference to field config)
- **Production Value**: The value used in production environment (optional for Overwrite mode)
- **Lower Environment Value**: The value used in staging/dev environments

### Update Modes

The module supports two update modes:

**Replace Mode** (default)
- Performs substring replacement within field values
- Searches for the production value and replaces it with the lower environment value
- Example: Replace "https://production.example.com" with "https://staging.example.com"
- Useful when only part of the field value needs to change (e.g., domain names in URLs)

**Overwrite Mode**
- Completely replaces all field values with the lower environment value
- Ignores the production value field
- Example: Set all email addresses to "test@example.com" regardless of current value
- Useful when you want to standardize values across all entities (e.g., test email addresses)

## REQUIREMENTS

This module requires the following:
- Drupal Core 11.0+
- PHP 8.3+

## INSTALLATION

Install as you would normally install a contributed Drupal module. For further
information, see:
https://www.drupal.org/docs/extending-drupal/installing-drupal-modules

1. Enable the module:
   ```bash
   drush en field_value_tracker
   ```

## CONFIGURATION

The module can be configured by visiting:
Administration » Configuration » Development » Field Value Tracker
(`/admin/config/development/field-value-tracker`)

From this interface you can:
- View all existing field value trackers in a table format showing all three
  field values
- Add new field value trackers using the "Add field value tracker item" button
- Edit existing trackers by clicking the "Edit" link
- Delete trackers by clicking the "Delete" link

### Creating Field Value Trackers

1. Navigate to `/admin/config/development/field-value-tracker`
2. Click "Add field value tracker item"
3. Fill in the form:
   - **Mode**: Select "Replace" (substring replacement) or "Overwrite" (complete replacement)
   - **Field Target**: Start typing the field label or ID to find the field (autocomplete widget)
     - Format: `entity_type.bundle.field_name` (e.g., `node.article.field_email`)
     - Uses entity reference to actual field configuration
   - **Production Value**: The value/substring to find in production (optional for Overwrite mode)
   - **Lower Environment Value**: The replacement value for lower environments (required)
4. Save the tracker

You will receive a confirmation message with a link to edit the newly created
tracker.

#### Example Configurations

**Replace Mode Example** (URL domain replacement):
- Mode: Replace
- Field Target: `paragraph.content_item.field_url`
- Production Value: `https://www.example.com`
- Lower Environment Value: `https://stage.example.com`

**Overwrite Mode Example** (standardized test email):
- Mode: Overwrite
- Field Target: `node.webform.field_notification_email`
- Production Value: (leave empty - not used)
- Lower Environment Value: `test@example.com`

### Integration with Other Modules

This module can integrate with other modules to provide enhanced functionality.
For example, other modules can implement form alters to lock the Field Target
field to specific values to enforce consistency. The field will be visible but
disabled for editing when such integrations are active.

## PERMISSIONS

The module defines one permission:

**Administer field value tracker**
- Allows creating, editing, deleting, and managing field value comparison
  entries
- Located under "Field Value Tracker" in the permissions interface

### Entity Structure

The module provides a `field_value_tracker` content entity with:

- **Entity Type ID**: `field_value_tracker`
- **Entity Label**: `Field Value Tracker`
- **Database Table**: `field_value_tracker`
- **Base Fields**:
  - `id`: Unique entity ID (integer, auto-increment)
  - `uuid`: Universally unique identifier (string)
  - `mode`: Update mode (list_string)
    - Options: `replace` (default) or `overwrite`
    - Required field
  - `target_field`: Entity reference to field configuration (entity_reference)
    - Target type: `field_config`
    - Uses custom selection handler: `default:field_config_selection`
    - Uses custom autocomplete widget: `field_config_autocomplete`
    - Required field
  - `prod_value`: Production environment value (string_long)
    - Optional field
    - Not required for Overwrite mode
  - `lower_env_value`: Lower environment value (string_long)
    - Required field
    - Used as replacement value in both modes

**Custom Features**:
- Field Target autocomplete widget for easy field selection
- Integration with field configuration entities
- Support for any field type that stores values in a database table

## DRUSH COMMANDS

The module provides Drush commands for updating field values programmatically.

### Available Commands

**field-value-tracker:update** (alias: `fvt:update`)

Updates field values from production to lower environment values based on configured trackers.

**Arguments:**
- `target_field` (optional): Specific field to update in format `entity_type.bundle.field_name`

**Options:**
- `--dry-run`: Preview changes without actually updating the database

**Safety Features:**
- **Production Environment Protection**: Automatically detects and blocks execution in production environments
  - Acquia: Checks `AH_SITE_ENVIRONMENT` environment variable (blocks when set to `prod`)
  - Pantheon: Checks `PANTHEON_ENVIRONMENT` environment variable (blocks when set to `live`)
  - Returns error message and exits without making changes
  - Intended for lower environments only (dev, test, stage)

**Behavior:**
- **Replace Mode**: Uses SQL `REPLACE()` function to substitute production value with lower environment value
  - Only updates rows where the production value is found (LIKE query)
  - Preserves other parts of the field value
  - Returns count of updated records
- **Overwrite Mode**: Directly sets all field values to the lower environment value
  - Updates all entities of the specified bundle
  - Ignores current field values
  - Returns count of updated records

**Output:**
- Processing information including mode, field type, and main property
- Success/error messages for each tracker
- Total count of updated records

**field-value-tracker:list** (alias: `fvt:list`)

Lists all configured field value trackers.

**Output:**
- Tracker ID
- Target field (entity_type.bundle.field_name)
- Production value (truncated to 50 characters)
- Lower environment value (truncated to 50 characters)

### Command Usage

```bash
# List all field value trackers
drush field-value-tracker:list
drush fvt:list

# Update all tracked field values (dry-run recommended first!)
drush field-value-tracker:update --dry-run
drush fvt:update --dry-run

# Update all tracked field values
drush field-value-tracker:update
drush fvt:update

# Update specific field target
drush fvt:update node.article.field_email

# Dry-run for specific field
drush fvt:update node.article.field_email --dry-run
```

**Understanding Command Output:**

The update command provides detailed information:
- Tracker ID and target field being processed
- Mode (Replace or Overwrite)
- Field type and main property name
- Preview of the replacement operation
- Number of records that will be/were updated
- Success or error messages for each tracker
- Total summary of all operations

### Database Sync Operations

#### Pantheon Environment

After syncing database from production to lower environments (dev/test), run:

```bash
# Connect to Pantheon environment
terminus drush site-name.env -- field-value-tracker:update

# Or using alias
terminus drush site-name.env -- fvt:update

# Preview changes first (recommended)
terminus drush site-name.env -- fvt:update --dry-run
```

**Pantheon Workflow Integration:**
Add to your `pantheon.yml` file to run automatically after database sync:

```yaml
workflows:
  sync_code:
    after:
      - type: webphp
        description: Update environment-specific field values
        script: private/scripts/field_value_sync.php
```

Create `private/scripts/field_value_sync.php`:
```php
<?php
/**
 * @file
 * Run field value tracker updates after DB sync.
 */

passthru('drush field-value-tracker:update');
?>
```

#### Acquia Environment

After database sync operations:

```bash
# Connect to Acquia environment via Cloud IDE or SSH
drush @sitename.env field-value-tracker:update

# Or direct SSH connection
ssh sitename.env@staging-1234.prod.hosting.acquia.com
cd /var/www/html/sitename.env/docroot
drush fvt:update
```

**Acquia Hooks Integration:**
Add to your `hooks/post-db-copy/field-value-sync.sh`:

```bash
#!/bin/bash
# Run after database copy to update environment-specific values
cd $HOME/$AH_SITE_NAME/docroot
drush field-value-tracker:update --yes
```

Make the hook executable:
```bash
chmod +x hooks/post-db-copy/field-value-sync.sh
```

### Best Practices

1. **Always run dry-run first** to preview changes:
   ```bash
   drush fvt:update --dry-run
   ```

2. **Production environment safety**: The command automatically blocks execution in production environments
   - Detects Acquia production (`AH_SITE_ENVIRONMENT=prod`)
   - Detects Pantheon production (`PANTHEON_ENVIRONMENT=live`)
   - No manual override available - this is intentional for safety

3. **Automate via platform hooks** for consistent deployment workflow

4. **Monitor output** for tracker IDs to identify which configurations are processed

5. **Test field targets** before production deployment to ensure correct field properties

## TESTING

The module includes comprehensive kernel test coverage:

### Running Tests

Using PHPUnit directly:
```bash
vendor/bin/phpunit -c project/tests/phpunit.xml project/modules/field_value_tracker/
```

Using Composer (if configured):
```bash
composer test:unit -- --filter=field_value_tracker
```

### Test Coverage

**Entity Tests** (`FieldValueTrackerTest`)
- Entity CRUD operations (create, read, update, delete)
- Replace and overwrite mode functionality
- Field validation (required fields)
- Entity reference to field configuration
- Default values and entity labels

**Drush Command Tests** (`FieldValueTrackerCommandsTest`)
- List command with/without trackers
- Update command in replace mode (substring replacement)
- Update command in overwrite mode (complete replacement)
- Dry-run functionality (no database changes)
- Targeted field updates (specific field only)
- Error handling (non-existent fields, invalid formats)
- Production environment blocking (Acquia and Pantheon)
- Non-production environment execution allowed
- Command output verification

**Test Requirements:**
- Drupal core modules: field, node, system, user, text, options
- Tests use kernel test base for database integration
- Custom test logger captures and verifies command output

## TROUBLESHOOTING

### Common Issues

**Tracker not updating values**
- Verify the field target format is correct (`entity_type.bundle.field_name`)
- Check that the field storage table exists in the database
- Ensure the production value exactly matches what's in the database (for Replace mode)
- Run with `--dry-run` first to see what would be updated

**"Field table does not exist" error**
- The field may not exist or may be a base field (not stored in a field table)
- Verify the field is attached to the bundle specified
- Check that the field has been used and has data

**No records updated in Replace mode**
- The production value may not exist in any entities
- Try using Overwrite mode if you want to set all values regardless of current content
- Check for whitespace or case sensitivity issues

**Permission denied errors**
- Ensure the user has the "Administer field value tracker" permission
- For Drush commands, ensure adequate server permissions

**"Cannot be run in production environments" error**
- This is a safety feature, not a bug
- The command detected you are in a production environment:
  - Acquia: `AH_SITE_ENVIRONMENT` is set to `prod`
  - Pantheon: `PANTHEON_ENVIRONMENT` is set to `live`
- This command is only intended for lower environments (dev, test, stage)
- There is no override flag - this is intentional for safety
- If you need to run this in production:
  1. Re-evaluate why you need to modify production field values
  2. Consider creating/modifying trackers in a lower environment first
  3. Test thoroughly in staging before any production changes

## MAINTAINERS

Current maintainers:
- [jhedstrom](https://www.drupal.org/u/jhedstrom)
- [Phase2](https://www.drupal.org/phase2)
