The purpose of this question was to replace old node images with a default image so as to reduce disk space usage, as old nodes are not frequently visited by users.
To achieve this first you load the node using node_load function, and grab the body field:
$node = node_load($nodeID);
$body = isset($node->body[$node->language][0]) ?$node->body[$node->language][0] : array();
$text = isset($body['value']) ? $body['value'] : $body['safe_value'];
After this you create DOMDocument object:
$doc = new DOMDocument(null, 'UTF-8');
Here, UTF-8 is for languages that are not Latin/Plain English.
$doc->loadHTML(mb_convert_encoding($text, 'HTML-ENTITIES', 'UTF-8'));
Convert your text to HTML entities following UTF-8 format.
$tags = $doc->getElementsByTagName('img');
You grab all your image tag from body.
Next, Loop through those tags:
foreach ($tags as $tag) {
// Get default Image.
$file_temp = file_get_contents($urlToDefaultImage);
// Get Image information.
$info = pathinfo($urlToDefaultImage);
// Replace if it exists.
$file = file_save_data($file_temp, 'public://' . $info['basename'], FILE_EXISTS_REPLACE);
// Get old image fid.
$oldImage = $tag->getAttribute('data-fid');
// Remove the file info from db and server if not used by any.
$status = file_delete(file_load($oldImage)),
$tag->setAttribute('src', file_create_url($file->uri));
$tag->setAttribute('data-fid', $file->fid);
}
After looping through each img tags save the newly generated HTML.
$replacedBody = $doc->saveHTML();
Remove extra html, body and Doctype from the new body using str_replace:
$replacedBody = str_replace('<html><body>', '', $replacedBody);
$replacedBody = str_replace('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">', '', $replacedBody);
$replacedBody = str_replace('</body></html>', '', $replacedBody);
Next update the newly formated body to node object:
$node->body[$node->language][0]['value'] = html_entity_decode($replacedBody);
$node->body[$node->language][0]['safe_value'] = html_entity_decode($replacedBody);
Save the node
node_save($node);
Bonus: Updating images in node image field.
Grab the field data.
$field = !empty($node->field_{machine_name}[$node->language]) ? $node->field_{machine_name}[$node->language] : array();
Here, {machine_name} represents the name for image field you created using Content UI.
// Loop through old images.
foreach($field as $key => $row) {
// Check if the image
if($row['type'] == 'image') {
// Get default Image.
$file_temp = file_get_contents($urlToDefaultImage);
// Get Image information.
$info = pathinfo($urlToDefaultImage);
// Replace if it exists.
$file = file_save_data($file_temp, 'public://' . $info['basename'], FILE_EXISTS_REPLACE);
// Change the current image with default.
$node->field_{machine_name}[$node->language][$key] = array(
'fid' => $file->fid,
'filename' => $file->filename,
'filemime' => $file->filemime,
'uid' => $file->uid,
'uri' => $file->uri,
'status' => $file->status,
'display' => 1,
);
}
}
Performing these operation will remove default image from your db and server and will save disk space. While we need to use file_delete function when removing files from body, it is not needed when when perform this operation while we replace on an image/media field. file_delete function will safely delete the files from server if that file is not used by any other nodes in website, if second parameter is not set to TRUE. While file_manage_delete does the same thing, though it will not lookup for database and check for its existing usage, it will simply release your disk space from that file, result in 404 not found image on other reused nodes.