Категория:
Опубликовано:

Импорт изображения из содержимого в поле

Image import

На днях обновлял один сайт на Drupal с 6-ки на 7-ю версию, и столкнулся с задачей переноса контента.

На сайте весь контент был свален в кучу, и добавлен в описание в виде HTML.

Пришлось немного повозится с парсингом изображений и разносом их по полям на новом сайте. Решил записать небольшой сниппет, так сказать - на следующий раз.

Импорт изображения из содержимого:

Для начала перенес весь контент, предварительно закодировав все HTML-сущности с помощью htmlentities (соответственно декодировал при вставке html_entity_decode). И работал с уже заполненным содержимым.

Легенда:

  • $node->body - поле "body" (содержащее контент)
  • www.site.com - условный адрес старого сайта
  • field_image - машинное имя поля для изображений

Сам сниппет:

$body = $node->body['und'][0]['value'];
preg_match_all('/<img[^>]+src=([\'"])?((?(1).+?|[^\s>]+))(?(1)\1)/', $body, $matches);
if(count($matches[2]) > 0){
  $images = array();
  foreach($matches[2] as $match){
    if($pos1 = stripos($match, 'http://www.site.com') == FALSE){
      $match = 'http://www.site.com'.$match;
    }
    $old_file = pathinfo($match);
    list($width, $height) = @getimagesize($match);
    $file_name = transliteration_clean_filename($old_file['basename'], language_default('language'));
    $image = file_get_contents($match);
    $file = file_save_data($image, 'public://'.$file_name, FILE_EXISTS_REPLACE);
    $images[] = array(
        'fid' => $file->fid,
        'alt' => '',
        'title' => '',
        'width' => $width,
        'height' => $height,
    );
  };
  $node->field_image['und'] = $images;
}
$node->body['und'][0]['value'] = preg_replace('/<img[^>]+>/i', '', $body);

Рассмотрим по порядку:

Присваиваем переменной $body значения поля содержащего HTML, затем функцией preg_match_all осуществляем поиск всех изображений (<img ... />) и записываем их в массив $matches:

$body = $node->body['und'][0]['value'];
preg_match_all('/<img[^>]+src=([\'"])?((?(1).+?|[^\s>]+))(?(1)\1)/', $body, $matches);

Проверяем наличие изображений (все ссылки с атрибута src будут храниться в массиве с ключом 2):

if(count($matches[2]) > 0){}

И, в случае их обнаружения выполняем следующее:

1. Создаем массив изображений $images

$images = array();

Циклом разбиваем массив со ссылками:

foreach($matches[2] as $match){}

В цикле, каждое вхождение проверяем на наличие полного адреса к изображению (для создания новых файлов), и если ссылка относительная - делаем её абсолютной:

if($pos1 = stripos($match, 'http://www.site.com') == FALSE){
  $match = 'http://www.site.com'.$match;
}

Получаем информацию о файле функцией pathinfo:

$old_file = pathinfo($match);

А также с помощью getimagesize узнаем и записываем в переменные ширину и высоту изображений:

list($width, $height) = @getimagesize($match);

Записываем имя файла:

$file_name = transliteration_clean_filename($old_file['basename'], language_default('language'));

Создаем новое изображение и сохраняем его:

$image = file_get_contents($match);
$file = file_save_data($image, 'public://'.$file_name, FILE_EXISTS_REPLACE);

Далее, записываем в массив изображений новое:

$images[] = array(
  'fid' => $file->fid,
  'alt' => '',
  'title' => '',
  'width' => $width,
  'height' => $height,
);

Закрываем цикл, и присваиваем полю с изображениями созданный массив:

$node->field_image['und'] = $images;

Ну, и напоследок, удаляем изображения из Body:

$node->body['und'][0]['value'] = preg_replace('/<img[^>]+>/i', '', $body);

Еще один сниппет для удаления битых изображений

Если к материалам были добавлены "битые" (с ошибками) изображения, проверить и удалить их можно с помощью следующего сниппета:

$images = $node->field_product_image['und'];
foreach($images as $image => $fid){
  $file = drupal_realpath($fid['uri']);
  list($width, $height) = @getimagesize($file);
  if($width == 0 || $height == 0){
    $file_l = file_load($fid['fid']);
    file_delete($file_l);
    unset($node->field_product_image['und'][$image]);
    node_save($node);
  }
};
$images = $node->field_product_image['und'];
if(count($images) == 0){
  unset($node->field_product_image['und']);
  node_save($node);
}
Если у Вас возникли вопросы, замечания, предложения или просто благодарность - пишите в комментариях.
Делитесь полезными материалами в социальных сетях.
Добавить комментарий