WordPress: Functions inside while loop with variable in the name - php

I'm trying to create a PHP while loop for WordPress that populates content to some Gravity Forms fields. I'm using Advanced Custom Fields with a repeater field to get the content and then trying to use eval() to create functions inside the while loop, like this:
if( have_rows( 'tickets', 'option' ) ) :
while( have_rows( 'tickets', 'option' ) ) : the_row();
$shortname = get_sub_field('short_name');
$image = get_sub_field('image');
add_filter( 'gform_field_value_' . $shortname . '_img', 'populate_' . $shortname . '_img' );
eval("
function populate_{$shortname}_img( $value ) {
return $image;
}
");
endwhile;
endif;
The problem is that I'm getting this error:
Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'populate_test_img' not found or invalid function name in /srv/www/nordstan/htdocs/wp-includes/plugin.php on line 235
(I'm getting multiples of these, of course, and one of the $shortname variables are "test".)
However, if I'm changing "return $image" to "return 'test'", no error message is printed and the whole thing is executed correctly, so the functions are created.
What am I doing wrong?
Thanks in advance!

Change the order...because your eval doesn't run until after the add_filter, add_filter is failing to find the function (that doesn't exist until run time).
$shortname = get_sub_field('short_name');
$image = get_sub_field('image');
eval("
function populate_{$shortname}_img( $value ) {
return '$image';
}
");
add_filter( 'gform_field_value_' . $shortname . '_img', 'populate_' . $shortname . '_img' );
also note that $image is a string and needs to be treated as such in the context of that eval'd code.

Related

I am not able to concatenate variable in php

I am making some changes to an existing Wordpress theme.
public function checkTv( $post ) {
global $title;
if ( ! empty( $post['season'] ) ) {
$videourl ='shows'.$title. $post['season'].'-'. $post['episodio'];
}
return $videourl;
}
Here the $videourl contains the desired URL format. Everything is working but the $title value is not being concatenated in the URL. It is being skipped automatically. In title i have the slug.
This how the call is being made
$postmeta = doo_postmeta_episodes($post_id);
$videourl = $this->checkTv( $postmeta );
$title has been declared as global and the value of the title is being taken from a function.
PHP does not skip the $title variable: It is undefined in your function and therefore empty. To use a variable which is defined outside the function you need to put the global directive inside of your function:
public function checkTv($post) {
global $title;
//...
}
This informs the function that the $title you're about to use is the same as the one declared outside the function.
Try this:
$videourl = 'shows'
. get_the_title($post)
. '-'
. $post['season']
. '-'
. $post['episodio'];
UPDATE: Based on the comment that you stated you need slug instead of title, try this:
$slug = get_post_field('post_name', $post);
$videourl = 'shows'
. $slug
. '-'
. $post['season']
. '-'
. $post['episodio'];
Thanks for your help. I solved it. The Problem was with the scope but declaring it global was not solving it. I passed a another parameter with $post in the function that I got from $post_id and it solved the problem.
thanks for your efforts

Custom Upload Directory does not change attachment meta

I'm trying to make a download script for a password protected wordpress site. To make use of PHPs readfile() function I need to retrieve the full attachment URL based on it's ID i am passing to the download script.
I made a Custom Post Type named Downloads and also changed it's upload directory to a folder inside wp-content also named downloads.
Here is the code for it:
add_filter( 'upload_dir', 'custom_upload_directory' );
function custom_upload_directory( $args ) {
$id = $_REQUEST['post_id'];
$parent = get_post( $id )->post_parent;
if( "downloads" == get_post_type( $id ) || "downloads" == get_post_type( $parent ) ) {
$args['path'] = WP_CONTENT_DIR . '/downloads';
$args['url'] = WP_CONTENT_URL . '/downloads';
}
return $args;
}
Upload works fine and when I click the link to the desired file, the ID is passed to a script via $_POST, which also works fine. But I just can't figure out a way to get the right file URL. Here's what I tried:
wp_get_attachment_url( $id ); // returns: example.com/wp-content/uploads/html/theme/wp-content/downloads/filename.ext
wp_get_attachment_link( $id ); // returns: slug
get_attachment_link( $id ); // returns: example.com/downloads/file (without .ext)
get_attached_file( $id, true ); // returns: html/theme/wp-content/downloads/filename.ext
get_post_meta( $id, '_wp_attached_file', false ); // returns: html/theme/wp-content/downloads/filename.ext
wp_get_attachment_metadata( $id ); // returns nothing
What I expected any of those functions to return was example.com/wp-content/downloads/filename.ext
But as you can see, some mix up the default upload directory and combine it with the new one while others just return half of the full URL (html/theme/... it's the directory the website sits on the server). So any ideas would be appreciated.
Hours, days and even weeks later I finally found an answer and modified it to fit my needs. I came as far as displaying the right URL (the modified one) inside the file upload lightbox of Wordpress. But after publishing/updating the post it went back to the same old .../wp-content/uploads/file.ext URL.
Someone else, somewhere else got exactly the same problem and fortunately it is said there, that you must not just alter $args['path'] and $args['url'] but you also have to alter basedir, baseurl and subdir.
So, the complete code to change a custom post types upload directory (in this case I chose the directory .../wp-content/downloads) is the following:
add_filter( 'upload_dir', 'change_upload_dir' );
function change_upload_dir( $args ) {
$id = $_REQUEST['post_id'];
if( get_post_type( $id ) == 'downloads' ) {
$args['basedir'] = wp_normalize_path( WP_CONTENT_DIR . 'downloads' );
$args['baseurl'] = content_url() . '/downloads';
$args['path'] = $args['basedir'];
$args['url'] = $args['baseurl'];
$args['subdir'] = '';
return $args;
}
}
So now, calling wp_get_attachment_url() finally results in something like example.com/wp-content/downloads/file.ext

HTML tags in WordPress file "functions.php"

I want to insert some HTML tags in a PHP variable, but it results in the PHP variable value only.
It gets the the_subtitle() value and inserts it in the PHP variable and finally adds it to the first part of $content. Why doesn't the HTML tags?
My code:
add_filter( 'the_content', 'add_before' , 20 );
function add_before($content) {
if ( the_subtitle() ){
$custom_content = '<h2 class="subtitlessss">' . the_subtitle() . '</h2><br>';
}
$content = $custom_content . $content;
return $content;
}
You're modifying the output of the_content() by using a filter. Your callback should return a value. However, the function you're using is going to output your subtitle rather than return it.
According to the plugin documentation it works in the same way as WordPress' the_title(). Initially I thought get_the_subtitle() would be more appropriate. However, that isn't the case. Tell the_subtitle() not to output instead (third argument).
function add_before( $content ) {
// Check if the subtitle has been set and assign the value to $subtitle
// Saves us having to call the same function again.
if ( $subtitle = the_subtitle( '<h2 class="subtitlessss">', '</h2><br />', false ) ) {
// Prepend to the content.
$content = $subtitle . $content;
}
// ALWAYS return content.
return $content;
}
add_filter( 'the_content', 'add_before', 20 );
The code you have will always run this line:
$content = $custom_content . $content;
Could that be the issue? Try only modifying $content if the_subtitle() returns a true value, like this:
add_filter( 'the_content', 'add_before', 20 );
function add_before( $content ) {
if ( the_subtitle() ) {
$custom_content = '<h2 class="subtitlessss">' . the_subtitle() . '</h2><br>';
$content = $custom_content . $content;
}
return $content;
}
If you are only seeing the value of $content as your code stands currently, then that means the_subtitle() isn't returning a true value so there is no value in $custom_content. This should throw a Notice: Undefined variable message. Does your wp-config have this line in it?
define('WP_DEBUG', true);
After researching the_subtitle()
OK, so it seems like the_subtitle() takes the same parameters as the native WordPress function the_title as the documentation says here:
Parameters Just like WP's built-in the_title() method,
the_subtitle() tag accepts three parameters:
$before (string) Text to place before the subtitle. Defaults to "".
$after (string) Text to place after the subtitle. Defaults to "".
Therefore, if you want HTML to come before and after the_subtitle, pass it as a parameter:
the_subtitle( '<h2 class="subtitlessss">','</h2><br>' );
To check if the function exists
Also, maybe we should be checking if the_subtitle exists instead of calling it in the if statement? Like so:
if ( function_exists( 'the_subtitle' ) )
The updated code for the entire excerpt would be this:
<?php
add_filter( 'the_content', 'add_before', 20 );
function add_before( $content ) {
if ( function_exists( 'the_subtitle' ) ) {
$custom_content = the_subtitle( '<h2 class="subtitlessss">','</h2><br>' );
$content = $custom_content . $content;
}
return $content;
}

Common php function called by other functions

Hello I would like to create two functions with different parameter but with a same common function. Here's my example...
The common function :
function my_responsive_pictures($post_id){
// Get alt text or set the $alt_text variable to the post title if no alt text exists
$alt_text = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
if ( !$alt_text ) { $alt_text = esc_html( get_the_title($post_id) ); }
// Get the info for each image size including the original (full)
$thumb_original = wp_get_attachment_image_src($attachment_id, 'slideshow');
$thumb_large = wp_get_attachment_image_src($attachment_id, 'slideshow-lg');
$thumb_medium = wp_get_attachment_image_src($attachment_id, 'slideshow-md');
$thumb_small = wp_get_attachment_image_src($attachment_id, 'slideshow-xs');
// Create array containing each image size + the alt tag
$thumb_data = array(
'thumb_original' => $thumb_original[0],
'thumb_large' => $thumb_large[0],
'thumb_medium' => $thumb_medium[0],
'thumb_small' => $thumb_small[0],
'thumb_alt' => $alt_text
);
// Echo out <picture> element based on code from above
echo '<picture>';
echo '<!--[if IE 9]><video style="display: none;"><![endif]-->'; // Fallback to <video> element for IE9
echo '<source srcset="' . $thumb_data['thumb_large'] . ', ' . $thumb_data['thumb_original'] . ' x2" media="(min-width: 800px)">';
echo '<source srcset="' . $thumb_data['thumb_medium'] . ', ' . $thumb_data['thumb_large'] . ' x2" media="(min-width: 400px)">';
echo '<source srcset="' . $thumb_data['thumb_small'] . ', ' . $thumb_data['thumb_medium'] . ' x2">';
echo '<!--[if IE 9]></video><![endif]-->'; // Fallback to <video> element for IE9
echo '<img srcset="' . $thumb_data['thumb_small'] . ', ' . $thumb_data['thumb_medium'] . ' x2" alt="' . $thumb_data['thumb_alt'] . '">';
echo '</picture>';
}
Another one which calls the common function :
function my_responsive_thumbnail($post_id){
// Get the featured image ID
$attachment_id = get_post_thumbnail_id($post_id);
my_responsive_pictures();
}
And a second one with other parameters $attachment_ID :
function my_responsive_acfthumbnail($post_id){
// Get the featured image ID
$attachment_id = get_field('image_bandeau');
my_responsive_pictures();
}
Nothing happens :(. What do I do wrong ? Thanx for your help...
Your function is expecting a parameter, and when you're calling it here
my_responsive_pictures();
you aren't passing anything.
You also have to call the my_responsive_thumbnail() function before it's going to make the subsequent calls to your "common" function.
There are a few issues with this code. The first thing we need to look at is the main function.
function my_responsive_pictures($post_id){
Your function definition doesn't give $post_id a default value therefore it's required any time you call the function. By attempting to call the function without passing an the argument you'll trigger an error.
$alt_text = get_post_meta($attachment_id, '_wp_attachment_image_alt', true);
if ( !$alt_text ) { $alt_text = esc_html( get_the_title($post_id) ); }
Here you're referring to $attachment_id which hasn't been set. When it's not found you're then getting the title of the post.
For this to work you'll need to set two parameters for the function.
function my_responsive_pictures( $attachment_id, $post_id ) {
Any time we call this function we need to pass in the $attachment_id (ID of the image) and $post_id (ID of the post).
Next up we need to modify the functions that ultimately call the main function.
function my_responsive_thumbnail( $post_id ) {
// Get the featured image ID
$attachment_id = get_post_thumbnail_id( $post_id );
// Now that we have the featured image ID, we really ought
// to do some error checking. Let's assume that all went well.
my_responsive_pictures( $attachment_id, $post_id );
}
This next function requires more attention. Remember that you're calling these functions with the post ID. You need to let get_field() know the ID of the post it should retrieve the image for.
function my_responsive_acfthumbnail( $post_id ) {
// Get the featured image ID
$attachment_id = get_field( 'image_bandeau', $post_id );
my_responsive_pictures( $attachment_id, $post_id );
}
Example usage:
my_responsive_acfthumbnail( get_the_ID() );
You may also want to consider setting a default for the post ID so you don't need to pass it in when retrieving an image for the current post you're viewing.
Finally, consider the level of duplication between the functions which call my_responsive_pictures. You'll want to check the attachment ID is valid so the functions are likely to become larger with only 1 line that's different.
Further information on get_field(): https://www.advancedcustomfields.com/resources/get_field/

How to insert a php code from another php file?

Im creating a custom function for my wordpress website that will add a review section below the post content and i need to insert this function from another another file into a custom function that i added to my functions.php. I need to get this piece of code $buffy .= $this->get_review(); from a different file to work in this function:
function content_injector($content) {
global $wp_query;
$postid = $wp_query->post->ID;
if (is_single((get_post_meta($postid, 'top_ad', true) != 'off' ))) {
$top_ad = do_shortcode('[td_ad_box spot_name="Ad spot -- topad"]');
}
if (is_single((get_post_meta($postid, 'bottom_ad', true) != 'off' ))) {
$bottom_ad = do_shortcode('[td_ad_box spot_name="Ad spot -- topad"]');
}
if (is_single()) {
$review = //HOW DO I ADD THAT get_review CODE HERE?
$custom_share = '<div id="title-deel"><h4 class="block-title"><span>DEEL</span></h4></div>' . do_shortcode('[ssba]');
$facebook_comments = '<div id="title-reageer"><h4 class="block-title"><span>REAGEER</span></h4></div>' . '<div class="fb-comments" data-href="' . get_permalink() . '" data-colorscheme="light" data-numposts="5" data-mobile="false" data-width="700"></div>';
}
$content = $top_ad . $content . $bottom_ad . $custom_share . $facebook_comments;
return $content;
}
add_filter('the_content', 'content_injector');
As you can see i need to add the get_review function to $review, but i cant make it work on my own. How to make this work?
Use include to include the file before using any methods from that file.
include("file_with_functions.php");
OR
Create a class (with filename same as classname).
Include the file.
Create an instance of the class.
Access the method in the class through the object

Categories