Как исправить неверно сериализованные данные на php

Работая с сайтом на Drupal 8 столкнулся с проблемой: после сброса кэша сайт ловил WSOD и отказывался работать. Ознакомившись с логами, заметил строку:

Error: Unsupported operand types in \web\modules\contrib\metatag\src\MetatagManager.php on line 371 #0 \web\modules\contrib\metatag\src\MetatagManager.php(121): Drupal\metatag\MetatagManager->getFieldTags()

После некоторого дебага причина была найдена: сайт переносился между хостингами и у него побилась таблица с сериализованными метатегами.

Чтобы запустить сайт: применим быстрый фикс, пересчитывающий сериализацию «на лету». Изменения коснутся контрибного модуля, и в качестве постоянного решения такой фикс использоваться не может.

web\modules\contrib\metatag\src\MetatagManager.php, функция getFieldTags():

protected function getFieldTags(ContentEntityInterface $entity, $field_name) {
    $tags = [];
    foreach ($entity->{$field_name} as $item) {
        // Get serialized value and break it into an array of tags with values.
        $serialized_value = $item->get('value')->getValue();
        if (!empty($serialized_value)) {

            $temp = @unserialize($serialized_value);

            // если не удаётся десериализовать в обычном порядке, пробуем исправить
            if (!$temp){
                $temp = preg_replace_callback ( '!s:(\d+):"(.*?)";!', function($match) {      
                return ($match[1] == strlen($match[2])) ? $match[0] : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
                },$serialized_value );

                $temp = unserialize($temp);
            }

            $tags += $temp;
        }
    }

    return $tags;
}

web\modules\contrib\metatag\src\Plugin\Field\FieldWidget\MetatagFirehose.php, функция formElement(): первый фрагмент заменяем на второй

if (!empty($item->value)) {
    $values = unserialize($item->value);
}

// заменяем на этот фрагмент
if (!empty($item->value)) {
  //$values = unserialize($item->value);

  $temp = @unserialize($item->value);

  if (!$temp){
    $temp = preg_replace_callback ( '!s:(\d+):"(.*?)";!', function($match) {      
      return ($match[1] == strlen($match[2])) ? $match[0] : 's:' . strlen($match[2]) . ':"' . $match[2] . '";';
    },$item->value );

    $temp = unserialize($temp);
  }

  $values = $temp;
}

После этого сайт запустится; чтобы исправить повреждённые данные в БД, можно пересохранить шаблоны метатегов, представления, ноды, термины, вручную (если их немного) или программно.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх