0

I have a question following my previous questions: Problem in displaying the WordPress shortcode function randomly and Calling multiple variables integrated with HTML in PHP arrays

As I asked in my previous question, I want to prevent duplicate shortcode content from appearing on my content page (for example, I may use this shortcode 5 times in an article and I don't want to have duplicate content in those 5 times. And Even if I had a total of 4 products and had used this shortcode 5 times and one less product would display an alternative text instead of displaying a duplicate product) and the codes of my previous question were correct, but now I want to integrate the values of the products in my previous code and the code What I wrote below is not correct because sometimes it displays duplicate products (I use these short codes in WordPress posts)

My code:

function get_product_id() {
    $args = array(
        'limit' => -1,
        'status' => 'publish',
        'return' => 'ids',
    );
    $all_products = wc_get_products( $args );
    $key = array_rand($all_products);
    $products_id = $all_products[$key];
    return $products_id;
}

function my_shortcode() {
    $products_id = get_product_id();
    $product = wc_get_product( $products_id );
    $product_price = $product->get_price();           
    $product_sale_price = $product->get_sale_price(); 
    $product_regular_price = $product->get_regular_price();
    if (isset($product_price) && $product_price > 0) {
        $product_price = number_format($product_price);  
    }
    if (isset($product_sale_price) && $product_sale_price > 0) {
        $product_sale_price = number_format($product_sale_price);  
    }
    if (isset($product_regular_price) && $product_regular_price > 0) {
        $product_regular_price = number_format($product_regular_price); 
    }
    $product_price_currency_symbol = get_woocommerce_currency_symbol();
    $image_id  = $product->get_image_id();
    $product_image = wp_get_attachment_image_url( $image_id, 'full' );  
    $product_title = $product->get_title();
    $product_link = $product->get_permalink();
    $discount = '';
    if ( $product->is_on_sale() ) {
        $max_percentage = 0;

        $percentage = 0;

        $price = $product->get_regular_price();
        $sale = $product->get_sale_price();

        if ( $price != 0 && ! empty( $sale ) ) {
            $percentage = ( $price - $sale ) / $price * 100;
        }
        if ( $percentage > $max_percentage ) {
            $max_percentage = $percentage;
        }
        
        if ($max_percentage <> 0) {
            $discount = '<div class="saved-sale">-' . round($max_percentage) . '% Off</div>';
        }
    } else {
        $product_regular_price = '';
    }
    
    
    $values = [
        '1' => '
            <a href="' . $product_link . '">
                <img src="' . $product_image . '">
                <span> '. $discount .' </span>
                <span> ' . $product_title . ' </span>
            </a>    
        ',
    ];

    if ( ! isset( $GLOBALS['my_shortcode_used'] ) ) {
        $GLOBALS['my_shortcode_used'] = [];
    }

    $post_id = get_the_ID();

    if ( ! isset( $GLOBALS['my_shortcode_used'][ $post_id ] ) || ! is_array( $GLOBALS['my_shortcode_used'][ $post_id ] ) ) {
        $GLOBALS['my_shortcode_used'][ $post_id ] = [];
    }

    $unused_values = array_diff( $values, $GLOBALS['my_shortcode_used'][ $post_id ] );

    if ( empty( $unused_values ) ) {
        $GLOBALS['my_shortcode_used'][ $post_id ] = [];
        $unused_values = $values;
    }

    $key = array_rand( $unused_values );

    $GLOBALS['my_shortcode_used'][ $post_id ][] = $unused_values[ $key ];

    return $unused_values[ $key ];
}
add_shortcode('jock', 'my_shortcode');

Is this code correct and standard? If not, please tell me where the problem is and what changes should I make.

Is there a solution that does not require me to repeat the arrays inside $values several times?

1 Answer 1

2

I have reviewed your code and you maintain a global array $GLOBALS['my_shortcode_used'] to track which products have already been shown in the post.

I have revised your code please check:

function get_product_id() {
    $args = array(
        'limit' => -1,
        'status' => 'publish',
        'return' => 'ids',
    );
    $all_products = wc_get_products( $args );

    $post_id = get_the_ID();
    $used_products = isset($GLOBALS['my_shortcode_used'][$post_id]) ? $GLOBALS['my_shortcode_used'][$post_id] : [];

    $unused_products = array_diff($all_products, $used_products);

    if(empty($unused_products)) {
        return null;
    }

    $key = array_rand($unused_products);
    $product_id = $unused_products[$key];

    $GLOBALS['my_shortcode_used'][$post_id][] = $product_id;

    return $product_id;
}

function my_shortcode() {
    $products_id = get_product_id();
    
    if(!$products_id) {
        return "All products ";  
    }

    $product = wc_get_product( $products_id );
    $product_price = $product->get_price();           
    $product_sale_price = $product->get_sale_price(); 
    $product_regular_price = $product->get_regular_price();
    
    if (isset($product_price) && $product_price > 0) {
        $product_price = number_format($product_price);  
    }
    if (isset($product_sale_price) && $product_sale_price > 0) {
        $product_sale_price = number_format($product_sale_price);  
    }
    if (isset($product_regular_price) && $product_regular_price > 0) {
        $product_regular_price = number_format($product_regular_price); 
    }
    
    $product_price_currency_symbol = get_woocommerce_currency_symbol();
    $image_id  = $product->get_image_id();
    $product_image = wp_get_attachment_image_url( $image_id, 'full' );  
    $product_title = $product->get_title();
    $product_link = $product->get_permalink();
    $discount = '';
    
    if ($product->is_on_sale()) {
        $max_percentage = 0;
        $percentage = 0;
        $price = $product->get_regular_price();
        $sale = $product->get_sale_price();
        if ($price != 0 && ! empty($sale)) {
            $percentage = ($price - $sale) / $price * 100;
        }
        if ($percentage > $max_percentage) {
            $max_percentage = $percentage;
        }
        if ($max_percentage <> 0) {
            $discount = '<div class="saved-sale">-' . round($max_percentage) . '% Off</div>';
        }
    } else {
        $product_regular_price = '';
    }
    
    $output = '
        <a href="' . $product_link . '">
            <img src="' . $product_image . '">
            <span> '. $discount .' </span>
            <span> ' . $product_title . ' </span>
        </a>';

    if ( ! isset( $GLOBALS['my_shortcode_used'] ) ) {
        $GLOBALS['my_shortcode_used'] = [];
    }

    $post_id = get_the_ID();

    if ( ! isset( $GLOBALS['my_shortcode_used'][ $post_id ] ) || ! is_array( $GLOBALS['my_shortcode_used'][ $post_id ] ) ) {
        $GLOBALS['my_shortcode_used'][ $post_id ] = [];
    }

    $values = ['1' => $output]; 

    $unused_values = array_diff( $values, $GLOBALS['my_shortcode_used'][ $post_id ] );

    if ( empty( $unused_values ) ) {
        return "Alternative text";
    }

    $key = array_rand( $unused_values );

    $GLOBALS['my_shortcode_used'][ $post_id ][] = $unused_values[ $key ];

    return $unused_values[ $key ];
}
add_shortcode('jock', 'my_shortcode');
Sign up to request clarification or add additional context in comments.

11 Comments

Thank you @Jenny, it worked perfectly and without any problems! Are the codes I wrote standard and without problems?
a question? When does this condition become true? if ( empty( $unused_values ) ) { return "Alternative text"; } I know when the variable $unused_values is empty I mean when does this variable $unused_values return an empty value? Because the value of $output is a constant value, so I think this condition will never be true. Did I understand correctly?
I asked this question to get more information, and I would be grateful if other friends know, to guide me.
$unused_values variable gets its value from the array_diff() function, which compares the array $values and $GLOBALS['my_shortcode_used'][$post_id] and If all elements from $values have been used then array_diff() will return an empty array, and empty($unused_values) will return true. So, the condition if (empty($unused_values)) will become true when all the values from $values have been used at least once in the current post.
If the "Alternative text" is not being displayed, then $GLOBALS['my_shortcode_used'][$post_id] is not being properly reset or managed, so $unused_values never becomes empty. so you should check the $unused_values and check what you get error_log(print_r($unused_values, true));
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.