-
-
Save adamsilverstein/e9c9993d938eae80e559d9eda8c0fdcc to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* Extract alt meta data from uploaded images. | |
* | |
* @wordpress-plugin | |
* Plugin Name: Extract Alt on Upload | |
* Description: Extract alt meta data from uploaded images. | |
* Plugin URI: | |
* Version: 1.0.0 | |
* Author: Adam Silverstein. | |
* License: GNU General Public License v2 (or later) | |
* License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
*/ | |
function filter_wp_read_image_metadata( $meta, $file ) { | |
$jpeg_contents = file_get_contents( $file ); | |
$value = false; | |
// Find the start and end positions of the XMP metadata | |
$xmp_start = strpos( $jpeg_contents, '<x:xmpmeta' ); | |
$xmp_end = strpos( $jpeg_contents, '</x:xmpmeta>'); | |
// Extract the XMP metadata from the JPEG contents | |
$xmp_data = substr( $jpeg_contents, $xmp_start, $xmp_end - $xmp_start + 12 ); | |
// Parse the XMP metadata using DOMDocument | |
$doc = new DOMDocument(); | |
$doc->loadXML( $xmp_data ); | |
// Instantiate an XPath object, used to extract portions of the XMP. | |
$xpath = new DOMXPath( $doc ); | |
// Register the relevant XML namespaces. | |
$xpath->registerNamespace( 'x', 'adobe:ns:meta/' ); | |
$xpath->registerNamespace( 'rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' ); | |
$xpath->registerNamespace( 'Iptc4xmpCore', 'http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/' ); | |
$node_list = $xpath->query( '/x:xmpmeta/rdf:RDF/rdf:Description/Iptc4xmpCore:AltTextAccessibility' ); | |
if ( $node_list && $node_list->count() ) { | |
// Get the alt text accessibility alternative most appropriate for the site language. | |
$node = $node_list->item( 0 ); | |
// Get the site's locale. | |
$locale = get_locale(); | |
// There are 3 possibilities: | |
// | |
// 1. there is an rdf:li with an exact match on the site locale | |
// 2. there is an rdf:li with a partial match on the site locale (e.g., site locale is en_US and rdf:li has @xml:lang="en") | |
// 3. there is an rdf:li with an "x-default" lang. | |
// | |
// we evaluate them in that order, stopping when we have a match. | |
$value = $xpath->evaluate( "string( rdf:Alt/rdf:li[ @xml:lang = '{$locale}' ] )", $node ); | |
if ( ! $value ) { | |
$value = $xpath->evaluate( 'string( rdf:Alt/rdf:li[ @xml:lang = "' . substr( $locale, 0, 2 ) . '" ] )', $node ); | |
if ( ! $value ) { | |
$value = $xpath->evaluate( 'string( rdf:Alt/rdf:li[ @xml:lang = "x-default" ] )', $node ); | |
} | |
} | |
} | |
if ( $value ) { | |
$callback = function( $attachment_id ) use ( &$callback, $value ) { | |
$attachment = get_post( $attachment_id ); | |
if ( ! wp_attachment_is_image( $attachment_id ) ) { | |
return; | |
} | |
update_post_meta( $attachment_id, '_wp_attachment_image_alt', $value ); | |
remove_action( 'add_attachment', $callback ); | |
}; | |
add_action( 'add_attachment', $callback ); | |
} | |
return $meta; | |
} | |
add_filter( 'wp_read_image_metadata', 'filter_wp_read_image_metadata', 10, 2 ); |
sorry to hear it broke, have you tried testing with the previous images? I don't know if its robust enough to work with every image.
I have installed the plugin "Enable Replace Media". Uploading a new image file adds the alt-text correctly. However when I replace the media the alt-text field gets cleared. Would you happen to know how to fix this? Updating the alt-text when replacing an image would be very helpful!
Hey @hlsautter - I assume you are talking about https://wordpress.org/plugins/enable-media-replace/? The gist relies on the wp_read_image_metadata
so perhaps that plugin removes it or overwrites what the gist does. You could try changing to a later priority:
change the last line to -
add_filter( 'wp_read_image_metadata', 'filter_wp_read_image_metadata', 99, 2 );
I would need to look at the plugin to see why its not quite compatible with this code. Hopefully this will land in core so you won't need my plugin.
Hey Adam this plugin is so useful. Installed it a week ago and it worked right out of the box. Strangely a week of site updates later it is still enabled and activated but does not work. Tried reinstalling and even copying your code to a new custom plugin... no dice. Currently on WP 6.8.2.