Skip to content

Instantly share code, notes, and snippets.

@vralle
Last active December 12, 2015 21:49
Show Gist options
  • Save vralle/1f9a79a42d0c35f3b00f to your computer and use it in GitHub Desktop.
Save vralle/1f9a79a42d0c35f3b00f to your computer and use it in GitHub Desktop.
Convert images to Shortcode
<?php namespace Vralle\Plugin\Shortcode\Img;
/*-------------------------------------------------------------------
* Convert images to Shortcode
*-----------------------------------------------------------------*/
function html_to_shortcode( $content ) {
// Returns, if content is empty
if( empty( $content ) ) return $content;
if( 'content_save_pre' === current_filter() )
$content = stripslashes( $content );
// Ignore DOMDocument errors On
libxml_use_internal_errors(true) AND libxml_clear_errors();
$html = new \DOMDocument( '1.0', 'UTF-8' );
// Load HTML as Document Fragment
// $html->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED );
$html->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ) );
$imgs = $html->getElementsByTagName( 'img' );
// Exit, If nothing
if( $imgs->length === 0 )
return $content;
// DOMDocument has a strange result for DOM manipulation in Loop. But strange Loop work perfect)
for( $i = $imgs->length - 1; $i >= 0; $i-- ) {
$image_attr_arr = [];
$link_attr_arr = [];
foreach( $imgs[$i]->attributes as $attr ) {
$image_attr_arr[ $attr->nodeName ] = $attr->nodeValue;
}
// Go to next image, if empty
if ( empty( $image_attr_arr[ 'src' ] ) ) {
continue;
} else {
// convert relative url to absolute
$image_attr_arr[ 'src' ] = rel2abs( $image_attr_arr[ 'src' ] );
}
// Check parent link
$parent = $imgs[$i]->parentNode;
// If link:
if( 'a' === $parent->nodeName ) {
// Save attributes
foreach( $parent->attributes as $attr ) {
if ( 'href' === $attr->nodeName ) {
$link_attr_arr[ 'url' ] = $attr->nodeValue;
} else {
$link_attr_arr[ 'link_' . $attr->nodeName ] = $attr->nodeValue;
}
}
}
// Get Attachment ID and Size
$attachment = get_attachment_id( $image_attr_arr['src'] );
// Set id
if( !empty( $attachment['id'] ) ) {
$image_attr_arr['attachment'] = $attachment['id'];
$image_attr_arr['size'] = $attachment['size'];
unset( $image_attr_arr['width'] );
unset( $image_attr_arr['height'] );
unset( $image_attr_arr['alt'] );
} else {
// remove id attrs
if( !empty( $image_attr_arr['class'] ) ) {
$image_attr_arr['class'] = preg_replace( '/wp-image-\d+/i', '', $image_attr_arr['class'] );
$image_attr_arr['class'] = preg_replace( '/size-\w+/i', '', $image_attr_arr['class'] );
}
unset( $image_attr_arr['attachment'] );
unset( $image_attr_arr['size'] );
// Check broken Images
if ( $size = @getimagesize( $src ) ) {
list( $width, $height ) = $size;
if ( empty( $image_attr_arr['width'] ) ) {
$image_attr_arr['width'] = $width;
}
if ( empty( $image_attr_arr['height'] ) ) {
$image_attr_arr['height'] = $height;
}
}
}
// Set align
if( !empty( $image_attr_arr['class'] ) ) {
if( preg_match( '/align(\w+)/i', $image_attr_arr['class'], $align ) ) {
$image_attr_arr['align'] = $align[1];
// remove align from class
$image_attr_arr['class'] = str_replace( $align[0], '', $image_attr_arr['class'] );
}
}
unset( $image_attr_arr['class'] );
// links checker
if( !empty( $link_attr_arr['url'] ) ) {
$link_attr_arr['url'] = rel2abs( $link_attr_arr['url'] );
if( isset( $image_attr_arr['attachment'] ) ) {
// Check link to post
if ( $link_attr_arr['url'] === get_attachment_link( $image_attr_arr['attachment'] ) ) {
$link_attr_arr['linkto'] = 'post';
// Check link to file
} elseif ( $link_attr_arr['url'] === wp_get_attachment_url( $image_attr_arr['attachment'] ) ) {
$link_attr_arr['linkto'] = 'file';
}
// Remove url
unset( $link_attr_arr['url'] );
} else {
$link_attr_arr['linkto'] = 'custom';
// Cleanup rel attrs
if( !empty( $link_attr_arr['rel'] ) ) {
$link_attr_arr['rel'] = preg_replace( '/attachment[\s+]?/i', '', $link_attr_arr['rel'] );
$link_attr_arr['rel'] = preg_replace( '/wp-att-[\d+][\s+]?/i', '', $link_attr_arr['rel'] );
}
}
}
$output = '[img';
foreach ( $image_attr_arr as $name => $value ) {
$output .= sprintf( ' %s="%s"', sanitize_key( $name ), esc_attr( $value ) );
}
if( !empty( $link_attr_arr ) ) {
foreach ( $link_attr_arr as $name => $value ) {
if( false !== array_search( $name, ['url', 'target', 'linkto'] ) ) {
$output .= sprintf( ' %s="%s"', sanitize_key( $name ), esc_attr( $value ) );
} else {
$output .= sprintf( ' link_%s="%s"', sanitize_key( $name ), esc_attr( $value ) );
}
}
}
$output .= ']';
// Create output
$shortcode = $html->createTextNode( $output );
if( !empty( $link_attr_arr ) ) {
$parent->parentNode->replaceChild( $shortcode, $parent );
} else {
$imgs[$i]->parentNode->replaceChild( $shortcode, $imgs[$i] );
}
}
$html->saveHTML( $html );
$content = $html->textContent;
if( 'content_save_pre' === current_filter() )
return addslashes( $content );
return $content;
}
add_filter( 'content_save_pre', __NAMESPACE__ . '\\html_to_shortcode', 1 );
// add_filter( 'content_edit_pre', __NAMESPACE__ . '\\html_to_shortcode' );
function shortcode2html( $content ) {
preg_match_all( '/' . get_shortcode_regex( ['img'] ) . '/', $content, $matches, PREG_SET_ORDER );
// See 'sub matches' for get_shortcode_regex in /wp-includes/shortcodes.php
if ( empty( $matches ) )
return $content;
foreach ( $matches as $shortcode ) {
$attrs = shortcode_parse_atts( $shortcode[3] );
$attr_img_string = '';
$attr_link_string = '';
// Setup Image Classes as WP Editor Attributes
$classes_arr = !empty( $attrs['class'] ) ? explode( ' ', $attrs['class'] ) : [];
if( !empty( $attrs['attachment'] ) ) {
// Pass Attachment ID to WP Editor
$wp_id = 'wp-image-' . intval( $attrs['attachment'] );
if( false === array_search( $wp_id, $classes_arr ) )
$classes_arr[] = $wp_id;
// Pass Size to WP Editor
$wp_size = 'size-' . $attrs['size'];
if( false === array_search( $wp_size, $classes_arr ) )
$classes_arr[] = $wp_size;
// Pass Link to WP Editor
if( !empty( $attrs['linkto'] ) ) {
if ( 'file' === $attrs['linkto'] ) {
$attrs['url'] = wp_get_attachment_url( $attrs['attachment'] );
} elseif ( 'post' === $attrs['linkto'] ) {
$attrs['url'] = get_attachment_link( $attrs['attachment'] );
}
}
}
// Pass align to WP Editor
if( !empty( $attrs['align'] ) ) {
$wp_align = 'align' . $attrs['align'];
if( false === array_search( $wp_align, $classes_arr ) )
$classes_arr[] = $wp_align;
// Remove Shortcode Attribute
unset( $attrs['align'] );
}
// Remove Shortcode Attributes
unset( $attrs['attachment'] );
unset( $attrs['size'] );
unset( $attrs['linkto'] );
$attrs['class'] = trim( implode( ' ', $classes_arr ) );
// list to string:
foreach( $attrs as $name => $value) {
if( 'url' === $name ) {
$attr_link_string .= ' href="' . $value . '"';
continue;
} elseif( false !== strpos( $name, 'link_' ) ) {
$name = str_replace( 'link_', '', $name );
$attr_link_string .= sprintf( ' %s="%s"', $name, $value );
continue;
}
$attr_img_string .= sprintf( ' %s="%s"', $name, $value );
}
$html = '<img' . $attr_img_string . '>';
if( ! empty( $attr_link_string ) ) {
$html = '<a' . $attr_link_string . '>' . $html . '</a>';
}
// Replace the shortcode:
$content = str_replace( $shortcode[0], $html, $content );
}
return $content;
}
add_filter( 'content_edit_pre', __NAMESPACE__ . '\\shortcode2html' );
<?php
/*
* Get an attachment ID given a URL.
* @param string $url
* @return array( ['id'], ['size'] )
*/
function get_attachment_id( $url ) {
$attachment = [];
$uploads = wp_upload_dir();
// Search Uploads URL. Return as $mat[1]
if ( preg_match( '|^' . preg_quote( $uploads['baseurl'] ) . '(.*)$|i', $url, $mat ) ) {
$file = pathinfo( $mat[1] );
$query = get_posts( [ 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'posts_per_page' => '-1' ] );
// exit if attachment posts not found(
if( empty( $query ) ) return;
foreach( $query as $post ) {
// Get all file data
$image_meta = get_post_meta( $post->ID, '_wp_attachment_metadata', true );
// 1. Check File URL.
if( false === strpos( $image_meta['file'], ltrim( $file['dirname'], '/' ) ) )
continue;
// Check match the base file
if( $file['basename'] === basename( $image_meta['file'] ) ) {
// 2. URL verified. Filename verified. Win!
$attachment['id'] = $post->ID;
$attachment['size'] = 'file';
// We are win!
break;
}
// Search matching available sizes
foreach( $image_meta['sizes'] as $key => $value ) {
if( $file['basename'] === basename( $value['file'] ) ) {
// 3. URL verified. Filename verified. Win!
$attachment['id'] = $post->ID;
$attachment['size'] = $key;
// We are win!
break 2;
}
}
}
}
return $attachment;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment