Subscribe to PHP Freaks RSS

Displaying exif information in WordPress posts

syndicated from planet-php.net on August 14, 2019

After discovering that WordPress modifies img tags when rendering a page, it crossed my mind that I could display exif information underneath each image on my new photography blog. The basic process is applicable to any manipulation of the content that you would want to do before it is displayed.

To do this, we add a new filter to the the_content hook:

add_filter('the_content', function ($content) {
	// manipulate $content
	return $content;
});

As with all filters, we have to return data in the same format as the first parameter to our function. For the_content, we receive a string which is the post's article text.

The core operation

In my case, all my <img> tags are immediately followed by a <figcaption> tag as I have a caption under each one. I decided to add the exif data within the <figcaption>.

We use regex to find the tags:

if (!preg_match_all( '@img [^>]+><figcaption>[^<]*</figcaption>@', $content, $matches)) {
  return $content;
}

This will store each <img> tag that's followed by a <figcaption> tag into the $matches variable, so we can now iterate over it:

foreach ($matches[0] as $match) {
  // Find the url in the  tag
  if (preg_match('@src="([0-9a-z:/._-]+)@i', $match, $srcList)) {
    $url = $srcList[1];
    if ($url) {
      $postId = attachment_url_to_postid($url);
      if ($postId) {
        $exif = ffp_create_exifcaption($postId);
        $new = str_replace('</figcaption>', $exif .'</figcaption>', $match);
        $content = str_replace($match, $new, $content);
      }
    }
  }
}

This code iterates over each match and finds the url in the src attribute of the image tag. We can then then load the post from that url using the rather helpful $postId = attachment_url_to_postid($url);.

Now that we have an ID, we can create the EXIF caption in a separate function and then finally we append it to the end of the current caption. We do this by simply replacing the closing </figcaption> with our text followed by </figcaption> which is a nice fast operation.

Creating EXIF display string

To create the string of EXIF data, I used a separate function to make it easier.

WordPress has already extracted the EXIF data we require when the image was uploaded into the admin, so we simply need to read it and format it. To get it we do this:

$metadata = wp_get_attachment_metadata($postId);
if (!isset($metadata['image_meta'])) {
  return '';
}
$imagemeta = $meta['image_meta'] ?? [];

$imagemeta is an array of useful characteristics about the image.

We pull the info we care into a set of variables like this:

$camera       = $imagemeta['camera'] ?? null;
$lens         = $imagemeta['lens'] ?? null;
$aperture     = $imagemeta['aperture'] ?? null;
$shutter      = $imagemeta['shutter_speed'] ?? null;
$iso          = $imagemeta['iso'] ?? null;
$focal_length = $imagemeta['focal_length'] ?? null;

if (! ($camera || $lens || $aperture || $shutter || $iso || $focal_length)) { return ''; }

(Obviously, if there is no data, there's nothing to do.)

Finally we format it nicely:

$string = '<aside class="exif">';

if ($camera) { $string .= '<div><ion-icon name="camera"></ion-icon><span>'.$camera.'</span></div>'; } if ($lens) { $string .='<div><ion-icon name="radio-button-on"></ion-icon><span>'.$lens.'</span></div>'; }

if ($aperture) { $aperture = 'f/' . $aperture; $string .= '<div><ion-icon name="aperture"></ion-icon><span>'.$aperture.'</span></div>'; }

if ($shutter) { $shutter = '1/' . (int)(1.0/(float)$shutter); $string .= '<div><ion-icon name="timer"></ion-icon><span>'.$shutter.'</span></div>'; }

if ($iso) { $string .= '<div><span class="text-icon">ISO</span><span>'.$iso.'</span></div>'; }

if ($focal_length) { $focal_length = (string)(round((float)$focal_length)) . 'mm'; $string .= '<div><ion-icon name="eye"></ion-icon><span>'.$focal_length.'</span></div>'; }

$string .= '</aside>'; return $string;

We wrap our entire EXIF string in an <aside> tag so that we can style appropriately. Then for each item of data, we display an icon followed by the text information. The icons are Io

Truncated by Planet PHP, read more at the original (another 950 bytes)