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

На днях обновлял один сайт на 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);
}
Делитесь полезными материалами в социальных сетях.