LinkFilter портит нечисловые/числовые ACF-значения: hotfix живёт только на проде ищу-сиделку.рф #2

Open
opened 2026-08-22 00:31:43 +05:00 by bryzgalov · 0 comments
Owner

Симптом

На сайте ищу-сиделку.рф после штатного обновления плагина 1.0.1 -> 1.1.0 страница /spb/ начала отдавать 404. Все остальные городские URL (/spb/uslugi/ и т.д.) работали.

Причина

LinkFilter::filter_acf_load_value() вешается на acf/load_value и прогоняет ЛЮБОЕ строковое значение через add_town_prefix(). Для полей типа page_link/post_object, где значение - это ID страницы (строка "5"), фильтр превращает 5 в /spb5. После этого get_field('main_page_alt', 'town_3') возвращает false, Router::route() не находит страницу для корня города и оставляет 404.

То же касается любых текстовых полей (телефоны, адреса, имена) - они получают префикс /spb.

Диагностика в веб-контексте на /spb/:

raw_option='5' | raw_termmeta='5'
get_field(main_page_alt, term_3) = false
get_field(index_town_alt, option) = false

Почему всплыло только сейчас

На проде в includes/class-link-filter.php версии 1.0.1 лежала ручная правка от 19.05.2026, которой нет в репозитории. Обновление до 1.1.0 её затёрло. Сейчас правка наложена на прод поверх 1.1.0 вручную - и будет затёрта снова при следующем обновлении.

Патч, который нужно внести в репозиторий

     public static function filter_acf_load_value($value, $post_id = null, $field = null)
     {
         if (!is_string($value)) {
             return $value;
         }
+        // Apply prefix only to actual paths/URLs, not arbitrary text values
+        // (phones, addresses, names, etc. should pass through unchanged).
+        $trimmed = ltrim($value);
+        if ($trimmed === '' || ($trimmed[0] !== '/' && !preg_match('~^https?://~i', $trimmed))) {
+            return $value;
+        }
         return self::add_town_prefix($value);
     }
 
     public static function add_town_prefix(string $url): string
     {
         if (Helpers::is_bypassed()) {
             return $url;
         }
+        // Skip pure numeric strings - they are likely IDs from page_link/post_object fields,
+        // not URLs. Without this, ACF page IDs (like "7") become "/spb7" which break readers
+        // doing (int) cast.
+        if (ctype_digit($url)) {
+            return $url;
+        }
 
         $town = Helpers::current_town();

Что сделать

  • Перенести патч в includes/class-link-filter.php
  • Добавить тесты: filter_acf_load_value не трогает "5", "+7 (812) 602-61-03", "Санкт-Петербург"; трогает "/uslugi/" и "https://<host>/uslugi/"
  • Выпустить 1.1.1 через release.sh
  • Обновить ищу-сиделку.рф штатным путём (снимет ручную правку с прода)
  • Проверить остальные сайты на этом плагине - там могла быть такая же несинхронизированная правка

Проверка после фикса

/spb/ -> 200, в шапке телефон СПб 8 (812) 602-61-03, title ... в Санкт-Петербурге и Ленинградской обл.

## Симптом На сайте ищу-сиделку.рф после штатного обновления плагина 1.0.1 -> 1.1.0 страница `/spb/` начала отдавать 404. Все остальные городские URL (`/spb/uslugi/` и т.д.) работали. ## Причина `LinkFilter::filter_acf_load_value()` вешается на `acf/load_value` и прогоняет ЛЮБОЕ строковое значение через `add_town_prefix()`. Для полей типа `page_link`/`post_object`, где значение - это ID страницы (строка `"5"`), фильтр превращает `5` в `/spb5`. После этого `get_field('main_page_alt', 'town_3')` возвращает `false`, `Router::route()` не находит страницу для корня города и оставляет 404. То же касается любых текстовых полей (телефоны, адреса, имена) - они получают префикс `/spb`. Диагностика в веб-контексте на `/spb/`: ``` raw_option='5' | raw_termmeta='5' get_field(main_page_alt, term_3) = false get_field(index_town_alt, option) = false ``` ## Почему всплыло только сейчас На проде в `includes/class-link-filter.php` версии 1.0.1 лежала **ручная правка от 19.05.2026**, которой нет в репозитории. Обновление до 1.1.0 её затёрло. Сейчас правка наложена на прод поверх 1.1.0 вручную - и будет затёрта снова при следующем обновлении. ## Патч, который нужно внести в репозиторий ```diff public static function filter_acf_load_value($value, $post_id = null, $field = null) { if (!is_string($value)) { return $value; } + // Apply prefix only to actual paths/URLs, not arbitrary text values + // (phones, addresses, names, etc. should pass through unchanged). + $trimmed = ltrim($value); + if ($trimmed === '' || ($trimmed[0] !== '/' && !preg_match('~^https?://~i', $trimmed))) { + return $value; + } return self::add_town_prefix($value); } public static function add_town_prefix(string $url): string { if (Helpers::is_bypassed()) { return $url; } + // Skip pure numeric strings - they are likely IDs from page_link/post_object fields, + // not URLs. Without this, ACF page IDs (like "7") become "/spb7" which break readers + // doing (int) cast. + if (ctype_digit($url)) { + return $url; + } $town = Helpers::current_town(); ``` ## Что сделать - [ ] Перенести патч в `includes/class-link-filter.php` - [ ] Добавить тесты: `filter_acf_load_value` не трогает `"5"`, `"+7 (812) 602-61-03"`, `"Санкт-Петербург"`; трогает `"/uslugi/"` и `"https://<host>/uslugi/"` - [ ] Выпустить 1.1.1 через `release.sh` - [ ] Обновить ищу-сиделку.рф штатным путём (снимет ручную правку с прода) - [ ] Проверить остальные сайты на этом плагине - там могла быть такая же несинхронизированная правка ## Проверка после фикса `/spb/` -> 200, в шапке телефон СПб `8 (812) 602-61-03`, title `... в Санкт-Петербурге и Ленинградской обл.`
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bryzgalov/wp-multi-city#2