Jump to content

ICT:Drupal 11.3 Technical Note - Custom tweaks

From Costa Sano MediaWiki

Drupal 11.3 Technical Note: Heritage Project Custom Tweaks

Overview

This document outlines the custom module created for the Heritage Project to handle specific user experience (UX) and data integrity requirements that are not met by core Drupal 11.3 configuration.

Features

  1. Status Message Link Removal: Replaces the linked node title in "Saved" messages with plain text for Historians, preventing them from leaving their View.
  2. Date Format Validation: Enforces a `dd/mm/yyyy` format on all text fields ending in `_day` and performs a calendar sanity check (e.g., blocking Feb 31st).

Implementation: heritage_tweaks.module

This code is stored in `web/modules/custom/heritage_tweaks/heritage_tweaks.module`.

<?php

/**
 * @file
 * Heritage Project: Link removal and Date Validation for Drupal 11.3.
 */

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;

/**
 * Implements hook_form_BASE_FORM_ID_alter() for node_form.
 */
function heritage_tweaks_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  
  // 1. LINK REMOVAL: Remove node link for non-admins.
  $form['actions']['submit']['#submit'][] = 'heritage_tweaks_clean_save_message';

  // 2. DATE VALIDATION: Target fields ending in _day.
  $form['#validate'][] = 'heritage_tweaks_date_validate';

  // 3. UI HINTING: Add placeholders to help users.
  foreach ($form as $key => &$element) {
    if (str_ends_with($key, '_day') && isset($element['widget']['value'])) {
      $element['widget']['value']['#attributes']['placeholder'] = 'dd/mm/yyyy';
    }
  }
}

/**
 * Removes the node link from the status message for non-administrators.
 */
function heritage_tweaks_clean_save_message($form, FormStateInterface $form_state) {
  if (\Drupal::currentUser()->hasPermission('administer nodes')) {
    return;
  }
  $messenger = \Drupal::messenger();
  $node = $form_state->getFormObject()->getEntity();
  $messenger->deleteByType(MessengerInterface::TYPE_STATUS);
  $messenger->addStatus(t('@type %title has been updated.', [
    '@type' => $node->type->entity->label(),
    '%title' => $node->label(),
  ]));
}

/**
 * Validates that fields ending in _day follow the dd/mm/yyyy format.
 */
function heritage_tweaks_date_validate(array &$form, FormStateInterface $form_state) {
  $values = $form_state->getValues();

  foreach ($values as $field_name => $value) {
    if (str_ends_with($field_name, '_day')) {
      
      $date_string = (is_array($value) && isset($value['value'])) ? $value['value'] : '';

      if (!empty($date_string)) {
        // Regex check for format: dd/mm/yyyy.
        $regex = '/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/([0-9]{4})$/';
        
        if (!preg_match($regex, $date_string)) {
          $form_state->setErrorByName($field_name, t('The date must be in dd/mm/yyyy format.'));
        } 
        else {
          // Calendar sanity check (Feb 30th, etc.).
          $parts = explode('/', $date_string);
          // PHP checkdate order: Month, Day, Year.
          if (!checkdate((int)$parts[1], (int)$parts[0], (int)$parts[2])) {
            $form_state->setErrorByName($field_name, t('This is not a valid calendar date.'));
          }
        }
      }
    }
  }
}

Maintenance Commands

Whenever this code is updated, clear the Drupal cache:

drush cr