How do I write a custom function in WordPress? - php

When I upload a featured image, I want to give it the a width of "100%" but only if it is over 1170px. If the width is between 1170px and 770px, I want it be get a width of "770px", otherwise the width will not be changed.
So far this code is doing what I want:
if (intval($width) >= 1170) {
$hwstring = 'width=100%';
} elseif ( (intval($width) < 1170) && (intval($width) >= 770) ) {
$hwstring = 'width=770px';
} else {
$hwstring = image_hwstring($width, 0);
};
However I have modified the media.php file inside the "wp-includes" folder which is apparently not the right way to do it. So how could I create a function that does the same thing without modifying the existing Wordpress code?
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
$html = '';
$image = wp_get_attachment_image_src($attachment_id, $size, $icon);
if ( $image ) {
list($src, $width, $height) = $image;
$hwstring = image_hwstring($width, $height);
if ( is_array($size) )
$size = join('x', $size);
$attachment =& get_post($attachment_id);
$default_attr = array(
'src' => $src,
'class' => "attachment-$size",
'alt' => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
'title' => trim(strip_tags( $attachment->post_title )),
);
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
$attr = wp_parse_args($attr, $default_attr);
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment );
$attr = array_map( 'esc_attr', $attr );
if (intval($width) >= 1170) {
$hwstring = 'width=100%';
} elseif ( (intval($width) < 1170) && (intval($width) >= 770) ) {
$hwstring = 'width=770px';
} else {
$hwstring = image_hwstring($width, 0);
};
$html = rtrim("<img $hwstring");
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
}
return $html;
}

Unfortunately there aren't any hooks for you to use to do this exactly in that function, but you can construct it yourself without modifying the core Wordpress files (which you don't want to do lest you overwrite your custom code when you upgrade). I'm kind of surprised that the wp_get_attachment_image_src() function doesn't pass the return values through filter to do exactly what you are talking about.
If you look at the top of this function, it gets the and array of $src, $width, $height by calling $image = wp_get_attachment_image_src($attachment_id, $size, $icon); You can make this same call yourself and construct your custom widths - basically copying the function into a custom version in functions.php or a custom functions plugin.
You can create a new ticket at http://core.trac.wordpress.org/newticket if you want to request this functionality to be added in a future version. The addition would be to wp_get_attachment_image_src() on line 515 (of the current trunk version of WP):
return apply_filters( 'wp_get_attachment_image_src', array( $src, $width, $height ), $attachment_id, $size, $icon );
EDIT: Ticket already exists, patch is a little weird, I submitted a new one but no guarantees as to when it will go in if it's approved..

Related

Add Missing Image Dimensions when Updating/Saving Post

I would like to automatically add missing image dimensions (width/height) to images (internal/external) when post is updated/saved. I found a way to do it when page is loaded but obviously it slows down the loading of the page.
This is original code. When added to the functions it does the job by adding image dimensions.
function add_img_size($content){
$pattern = '/<img [^>]*?src="(https?:\/\/[^"]+?)"[^>]*?>/iu';
preg_match_all($pattern, $content, $imgs);
foreach ( $imgs[0] as $i => $img ) {
if ( false !== strpos( $img, 'width=' ) && false !== strpos( $img, 'height=' ) ) {
continue;
}
$img_url = $imgs[1][$i];
$img_size = #getimagesize( $img_url );
if ( false === $img_size ) {
continue;
}
$replaced_img = str_replace( '<img ', '<img ' . $img_size[3] . ' ', $imgs[0][$i] );
$content = str_replace( $img, $replaced_img, $content );
}
return $content;
}
add_filter('the_content','add_img_size');
I tried editing it by using add_action save_post/pre_post_update but it does nothing.
add_action('save_post','add_img_size');
function add_img_size($post_id){
What am i missing? Can someone help me edit it so it adds image dimensions when post is updated/saved? Seemed simpler than it is..
function set_image_dimensions( $id, $post ) {
if ( ! wp_is_post_revision( $post ) ){
remove_action('save_post', 'set_image_dimensions', 10, 2 );
$content = $post->post_content;
$pattern = '/<img [^>]*?src="(https?:\/\/[^"]+?)"[^>]*?>/iu';
preg_match_all($pattern, $content, $imgs);
foreach ( $imgs[0] as $i => $img ) {
if ( false !== strpos( $img, 'width=' ) && false !== strpos( $img, 'height=' ) ) {
continue;}
$img_url = $imgs[1][$i];
$img_size = #getimagesize( $img_url );
if ( false === $img_size ) {
continue;}
$replaced_img = str_replace( '<img ', '<img ' . $img_size[3] . ' ', $imgs[0][$i] );
$content = str_replace( $img, $replaced_img, $content );
}
$post->post_content = $content;
wp_update_post( $post );
add_action( 'save_post', 'set_image_dimensions', 10, 2 );
}}
add_action( 'save_post', 'set_image_dimensions', 10, 2 );
This works as i wanted. Adds missing image dimension on update.
In the end when i started with post_content and ended with wp_update_post had no errors to deal with and it didn't work. The culprit was using $content = $post->post_content; instead the other way around the second time.
Got around infinite loop with help of link Shoelaced posted.

WordPress wp-insert-post function creating arbitrary no-title pages

I am using the wp-insert post function to dynamically generate pages from a website I am working on. However, I have been getting these no title posts that increase every time I refresh the page along with the actual pages that are generated from my code.
I have tried solving this by adding a hook into my page creation process, however this does not seem to do anything. I was wondering how I can only create the pages I need without these no title posts appearing.
My code:
if( !class_exists("PageCreator")) {
class PageCreator
{
public function __construct()
{
add_action('init', array($this, 'AddThisPage'));
}
public function AddThisPage()
{
$dirName = "/zotpull/resources/temp/";
$filename = dirname(__DIR__, 2) . $dirName . "useData.txt";
$theFile = fopen($filename, "r");
$msg = fread($theFile, filesize($filename));
fclose($theFile);
$links = explode("\n", $msg);
foreach( array_slice($links, 0, count($links) -1) as $item ) {
$item = str_replace("/","-",$item);
$str2 = substr($item, 5);
$page = array(
'page_template' => 'datePage.php', //Sets the template for the page.
'post_title' => $str2, //The title of your post.
'post_status' => 'publish',
'post_type' => 'page'
);
if ( ! function_exists( 'post_exists' ) ) {
require_once( ABSPATH . 'wp-admin/includes/post.php' );
}
$page_exists = post_exists($page['post_title']);
if ($page_exists == 0) {
$insert = wp_insert_post($page);
}
}
}
}
}
Try to use wp_update_post after wp_insert_post. check the below code.
if( !class_exists("PageCreator")) {
class PageCreator{
public function __construct()
{
add_action('init', array($this, 'AddThisPage'));
}
public function AddThisPage()
{
$dirName = "/zotpull/resources/temp/";
$filename = dirname(__DIR__, 2) . $dirName . "useData.txt";
$theFile = fopen($filename, "r");
$msg = fread($theFile, filesize($filename));
fclose($theFile);
$links = explode("\n", $msg);
foreach( array_slice($links, 0, count($links) -1) as $item ) {
$item = str_replace("/","-",$item);
$str2 = substr($item, 5);
$page = array(
'page_template' => 'datePage.php', //Sets the template for the page.
'post_title' => $str2, //The title of your post.
'post_status' => 'publish',
'post_type' => 'page'
);
if ( ! function_exists( 'post_exists' ) ) {
require_once( ABSPATH . 'wp-admin/includes/post.php' );
}
$page_exists = post_exists($page['post_title']);
if ($page_exists == 0) {
$insert = wp_insert_post($page);
$my_post = array(
'ID' => $insert,
'post_title' => $str2
);
wp_update_post( $my_post );
}
}
}
}
}

Get the product ID in woocommerce_product_get_image filter hook

Some of our products are using an external image instead of the post thumbnail, I have an acf set up for this url. It appears that you can filter the woocommerce get_image() function, but I can't find a way to get the current product's id to get the field.
Here's what I have so far:
function offsite_product_images($image_url, //variable $this wont work here){
//need some way to get the current product's id
if(get_field('thumbnail_url', $id)){
$image_url = get_field('thumbnail_url', $id);
}
return $image_url;
}
add_filter( 'woocommerce_product_get_image', 'offsite_product_images');
the woocommerce get_image() function:
public function get_image( $size = 'woocommerce_thumbnail', $attr = array(), $placeholder = true ) {
if ( has_post_thumbnail( $this->get_id() ) ) {
$image = get_the_post_thumbnail( $this->get_id(), $size, $attr );
} elseif ( ( $parent_id = wp_get_post_parent_id( $this->get_id() ) ) && has_post_thumbnail( $parent_id ) ) {
$image = get_the_post_thumbnail( $parent_id, $size, $attr );
} elseif ( $placeholder ) {
$image = wc_placeholder_img( $size );
} else {
$image = '';
}
return apply_filters( 'woocommerce_product_get_image', wc_get_relative_url( $image ), $this, $size, $attr, $placeholder, $image );
}
I even tried changing the function to pass the id directly, but it wouldn't do it.
Any help on getting the product or it's id passed to my filter would be greatly appreciated.
Your function code is incomplete, there is some missing arguments as the WC_Product object, that you need to get the product ID. Try the following:
add_filter( 'woocommerce_product_get_image', 'offsite_product_images', 10, 5 );
function offsite_product_images( $image, $product, $size, $attr, $placeholder ){
if( get_field('thumbnail_url', $product->get_id() ) ){
$image = get_field('thumbnail_url', $product->get_id() );
}
return $image;
}
Code goes in functions.php file of your active child theme (or active theme). It should work.

How can I process multiple image ids through a wordpress shortcode?

Im trying to pass multiple image ids through a wordpress shortcode, currently my wordpress shortcode is as follows:
[lemonslider images="35,46,43,42,41"]
And my function for this as follows, the idea was for each image id it would return a html image string for each of the image ids, but currently it only generates one:
// LEMON SLIDER SHORTCODE
function lemon_slider( $atts ){
$a = shortcode_atts( array(
'images' => '44',
'toshow' => '5',
), $atts );
$SlImages = $a['images'];
$arrlength = count($SlImages);
for($x = 0; $x < $arrlength; $x++) {
$image_attributes = wp_get_attachment_image_src( $attachment_id = $SlImages);
return ('<img src=' . $image_attributes[0] . ' width=' . $image_attributes[1] . ' height=' . $image_attributes[2] . ' />');
}
}
add_shortcode( 'lemonslider', 'lemon_slider' );
Ive been looking at foreach loops but Im not sure how to return multiple values.
my output is 1 and it supposed to 5.
Split your images attribute on the comma, and don't return directly from the loop.
Add your generated image tags to a string and return the string after the loop.
function lemon_slider( $atts ){
$a = shortcode_atts( array(
'images' => '44',
'toshow' => '5',
), $atts );
$SlImages = $a['images'];
$arrlength = count($SlImages);
// split images parameter on the comma
$SlImages = explode(",", $a['images']);
// define an empty string for the initial return value
$ret = "";
foreach ($SlImages as $image) {
$image_attributes = wp_get_attachment_image_src( $attachment_id = $image);
// add each image tag to the return string
$ret .= ('<img src=' . $image_attributes[0] . ' width=' . $image_attributes[1] . ' height=' . $image_attributes[2] . ' />');
}
// return the result
return $ret;
}
add_shortcode( 'lemonslider', 'lemon_slider' );

Add attribute to wp_get_attachment_image

I'm trying to add an attribute to the result of wp_get_attachment_image.
I want to use jquery lazyload to handle loading of my post thumbnails and to do that I need to add a data-original= attribute to the <img> tag wp_get_attachment_image is creating.
I've tried:
$imgsrc = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), "full" );
$imgsrc = $imgsrc[0];
$placeholderimg = wp_get_attachment_image( 2897, "full", array('data-original'=>$imgsrc) );
But it doesn't add the data attribute as I expected.
<img class="attachment-full" width="759" height="278" alt="..." src="..."></img>
Looking at the wp_get_attachment_image function it would seem that this ought to work though:
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
$html = '';
$image = wp_get_attachment_image_src($attachment_id, $size, $icon);
if ( $image ) {
list($src, $width, $height) = $image;
$hwstring = image_hwstring($width, $height);
if ( is_array($size) )
$size = join('x', $size);
$attachment =& get_post($attachment_id);
$default_attr = array(
'src' => $src,
'class' => "attachment-$size",
'alt' => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
'title' => trim(strip_tags( $attachment->post_title )),
);
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
$attr = wp_parse_args($attr, $default_attr);
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment );
$attr = array_map( 'esc_attr', $attr );
$html = rtrim("<img $hwstring");
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
}
return $html;
}
Where am I going wrong?
[update] Sometimes it just takes a fresh pair of eyes to spot the idiocy... Thanks to hobo I realised I simply missed out a parameter in my function call :D :P
I haven't tested, but I think the problem is your array should be the fourth argument to wp_get_attachment_image, not the third.
So
$placeholderimg = wp_get_attachment_image( 2897, "full", array('data-original'=>$imgsrc) );
should be
$placeholderimg = wp_get_attachment_image( 2897, "full", false, array('data-original'=>$imgsrc) );
assuming you're happy with the default value (false) of the $icon argument.
I personally solved this problem doing a string replacement:
$imgsrc = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), "full" );
$imgsrc = $imgsrc[0];
$placeholderimg = wp_get_attachment_image( 2897, "full" );
$placeholderimg = str_replace( "<img ", "<img data-original='$imgsrc'", $placeholderimg );
It's not an elegant solution but it can work in some contexts (for example, you may have the attributes saved in a string and not as an array as in your case).

Categories