*/
class Add_Img_Maps_Public {
/**
* The ID of this plugin.
*
* @since 1.0.0
* @access private
* @var string $plugin_name The ID of this plugin.
*/
private $plugin_name;
/**
* The version of this plugin.
*
* @since 1.0.0
* @access private
* @var string $version The current version of this plugin.
*/
private $version;
/**
* A tracker of the images on the current page.
*
* Structure:
* `[ from => [ content/header/thumbnail ], image => $image ]`
*
* @since 1.0.0
* @access private
* @var array $images List of image post objects
*/
private $images = array();
/**
* Initialize the class and set its properties.
*
* @since 1.0.0
* @param string $plugin_name The name of the plugin.
* @param string $version The version of this plugin.
*/
public function __construct( $plugin_name, $version ) {
$this->plugin_name = $plugin_name;
$this->version = $version;
$this->add_img_maps_options = get_option($this->plugin_name);
}
/**
* This does not enqueue any CSS, and the Javascript is enqueued within
* the footer hook, so there are no specific enqueue_* functions.
*/
/**
* Options prototyped and rejected:
*
* 1. Handling the wp_get_attachment_image_attributes hook & adding 'usemap'
* 2. Handling the modify_header_image_data to add 'usemap' attribute
*
* The problem with both these low-level handlers is that it's up to the
* template whether to use the functions that call them.
*/
/**
* Find all images attached (db-wise) to the post, and add them to $images.
*
* The function is hooked into this_post, so called once on single pages
* and multiple times on lists.
*
* @acess public
* @var WP_Post $post The current post.
* @return null
*
*/
public function list_images($post) {
//error_log('Add_Img_Maps_Public->append_maps()');
try {
// find the images (DB query) with IDs
if ( $this->add_img_maps_options['content'] ) {
$children =
get_children( // Start a new query for our registered images
array(
'post_parent' => $post->ID, // Get data from the current post
'post_type' => 'attachment', // Only bring back attachments
'post_mime_type' => 'image', // Only bring back attachments that are images
'post_status' => 'all', // Attachments default to "inherit", rather than published.
// Use "inherit" or "all".
)
)
;
foreach ( $children as $child_image ) {
if ( isset( $this->images[ $child_image ->ID ] )) {
array_push( $this->images[ $child_image->ID ]['from'], 'content' );
} else { //new image, add
$this->images[ $child_image->ID ] = array (
'image' => $child_image,
'from' => array('content'),
);
}
//error_log('Found image ID ' . $child_image->ID . ' "' . $child_image->post_title . '"' );
}
} // end if content option set
// If we're including featured images, check the featured image too.
if ( $this->add_img_maps_options['thumbnail'] ) {
// Includes check for 'has feature support'
$thumbnail_id = get_post_thumbnail_id();
if ( $thumbnail_id ) {
if ( isset( $this->images[ $thumbnail_id ] )) {
array_push( $this->images[ $thumbnail_id ]['from'], 'thumbnail' );
} else { //new image, add
$this->images[ $thumbnail_id ] = array (
'image' => get_post($thumbnail_id),
'from' => array('thumbnail'),
);
}
//error_log('Added featured image: ' . $thumbnail_id );
}
}
} catch ( Exception $e) { //anything go wrong?
//If it failed, record it and mention it to admins
if ( current_user_can('activate_plugins') ) {
?>
';
error_log ("Add_Img_Maps execption caught on public page: $e" );
} // end of try/catch
} // end 'the_content' hook
/**
* Add the header to the lists & output image maps in footer.
*
* Also, optionally, sets up the Javascript that will attach maps to images.
*
* @access public
* @var none
* @return none
*/
public function append_maps() {
try {
//if 'header' is turned on.
/* Do this last because it passes not an image object, but a 'StdClass' object
* with properties: url, url_thumbnail, width, height, attachment_id
*/
if ( $this->add_img_maps_options['header'] ) {
$header_image = get_custom_header(); // returns stdClass object with limited field
if ( $header_image ) {
// error_log('Header image: ' . print_r( $header_image, true));
$header_image->ID = $header_image->attachment_id ;
// In unlikely situation of being both header & content
if ( isset( $this->images[ $header_image->attachment_id ] )) {
array_push( $this->images[ $header_image->attachment_id ]['from'], 'header' );
} else { //new image, add
$this->images[ $header_image->ID ] = array (
'image' => $header_image,
'from' => array('header'),
);
}
//error_log('Head image ID=' . $header_image->attachment_id);
}
}
//error_log( 'images: ' . print_r($this->images, true) );
// Of course, this doesn't tell me which size of the page is included in the page.
// Rather than interrogate the page, I'll dump all the image maps and let Javascript sort it out.
// Track all images with maps
$images_with_maps = array();
foreach( $this->images as $ID => $image ) {
if ( ! is_object( $image['image'] ) ) {
throw new Exception("Expected image to be object. Is not: " .
print_r ( $image['image'], true ));
}
// Does it have a map?
$maps_metadata = get_post_meta( $image['image']->ID, Add_Img_Maps::get_key(), true );
if ( $maps_metadata ) {
$image['maps']=$maps_metadata;
$images_with_maps[ $ID ] = $image;
}
}
// If there's nothing to see, we move on.
if ( ! $images_with_maps ) {
return;
}
//error_log( 'images_with_maps: ' . print_r($images_with_maps, true) );
// The srcset option is either 'run' [responsive images] or 'off'
?>' > $image ) {
// for HANDLE_SIZES, will need to fetch image metadata, create
// an array of sizes, and add a 'data-width' attribute to each
// map to help find the size.
foreach ( $image['maps'] as $size => $map ) {
$elementId = Add_Img_Maps_Map::get_map_id( $ID, $size );
if ( $image['image'] instanceof stdClass ) {
/* Due to a bug in either WP or UniqueHeader, stdClass->URL
* always point to the default header & cannot be trusted
* if there's a unique header-per-post plugin.
*/
$image['image'] = get_post( $ID );
$url = wp_get_attachment_url( $ID );
// Else a WP_Post object
// If the GUID ends in a file suffix, assume it is a URL* (see below)
} else if ( preg_match( '/\.\w{3,5}$/', $image['image']->guid ) ) {
$url = $image['image']->guid;
// else just look it up
} else {
$url = wp_get_attachment_url( $image['image']->ID );
}
$attrs = array(
'id' => $elementId,
'data-from' => implode( ',' , $image['from'] ),
'data-image-id' => $ID,
// Oddly, urls are stored on attachment WP_POst object GUIDs
// (which stores, for post/page types, UIDs for feed readers)
'data-url' => esc_url($url),
'data-size' => $size,
// Other options include WP_POST->slug & header->url_thumbnail
// Will add a data-width attribute for HANDLE_SIZES
);
if ( ! $map instanceof Add_Img_Maps_Map ) {
throw new Exception( 'Expected map object. Is ' .
print_r ( $map, true ) );
}
echo $map->get_html( $attrs );
}
}
?>add_img_maps_options['imagemapresizer'] ) {
wp_enqueue_script(
'image-map-resizer',
plugin_dir_url( __FILE__ ) . 'js/imageMapResizer.js',
array('jquery'),
$this->version,
true
);
}
//error_log( print_r( $this->add_img_maps_options , true ));
wp_enqueue_script(
$this->plugin_name,
plugin_dir_url( __FILE__ ) . 'js/add-img-maps-public.js'
, array( 'jquery' ),
$this->version,
true
);
} catch ( Exception $e) { //anything go wrong?
//If it failed, record it and mention it to admins
if ( current_user_can('activate_plugins') ) {
?>
';
error_log ("Plugin Add_Img_Maps caught Exception: $e" );
} // end of try/catch
}
}
/* *About that GUID kludge. The GUID is meant to store a unique ID for RSS
* feed readers, and that's the function it performs for post/page objects.
* For images, it seems to be used for the URL. But I can't see from the
* documentation if that's a feature or an accidental side-effect that I
* cannot rely on. So I've tried to use it to save time if present, and make
* another DB call if I have to.
*/