Question regarding ob_flush and flush not working on FPM

I have below code and want to show echo one by one but whole result returns at once


<?php 



for ($i = 1; $i <= 10; $i++){

  

  sleep(1); 

  echo "$in";

  

  ob_flush();

    flush();

  

}

It is ok in CGI but not in FPM (PHP 8.3 – apache 2.4)

I have tried several things to solve this problem, but none of these solutions worked.
Here are some of them:

ini_set('output_buffering','Off');
ini_set('zlib.output_compression',0);
ini_set('implicit_flush',1);
ob_end_clean();
set_time_limit(0);
ob_implicit_flush(true);
ob_end_flush();
ob_start();

Any solution?

Custom Elementor Widget Icon

I am creating the custom widgets and I was thinking as is there any was that I can replace the elementor given icons with my own svg file?

Elementor Admin Widgets area:

enter image description here

With something like this:

enter image description here

I tried the below code but not getting result:

.elementor-panel .elementor-element .icon i[class*="example-"] {
    width: 24px;
    height: 24px;
    display: block;
    margin: 0 auto;
    text-align: center;
}

.example-2-buttons {
    background-image: url(../../../../../plugins/example/assets/images/history-custom-icon.svg) !important
}

I also tried the below code as well:

.elementor-element .icon .class-name:before {
    content: "";
    background-image: url(../../../../../plugins/example/assets/images/history-custom-icon.svg) !important;
    height: 30px;
    display: block;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center center;
}

And this as well and this also through error:

function custom_admin_icon_css()
{
  echo '<style>
      .example {
          display: inline-block;
          width: 24px;
          height: 24px;
          background-image: url(../../../../../plugins/example/assets/images/history-custom-icon.svg) !important;
          background-size: contain;
          background-repeat: no-repeat;
          background-position: center;
      }
  </style>';
}
add_action('elementor/editor/after_enqueue_scripts', 'custom_admin_icon_css');

Remove multiple n in PHP String from beginning and end of a string in this somewhat unique case

I am stuck with figuring out how to properly fix formatting from an older database.

Note, that just trimming the data or removing all n’s is not what I am looking for, I need it a bit more complex – which is where I struggle to figure out.

I tried different scripts I found online, tampering with them, rewriting them, testing a lot, and nothing really works the way I need it to :/ I just can not figure out the logic how to write a script to do that


So I have 5000+ strings I need to do this on, so I need a solid function to use to loop through all of it. Here is what I am trying to do:

I need to remove all formatting (just multiple n or one n or mix) from beginning of the string, and from the end of the string. Let me post 3 examples of the strings (pulled from db to make it simple to do tests):

<?php
$data = 'n n Member of the public council of Enlightening Movement Enlightenment Movementn Fakori Beheshti (20160517)n MP Raihana Azad (20170910)n n The &quot;Enlightening movement&quot; is a Hazara controlled social movement promoting Hazara affairs in Afghanistan. It has international supporters mostly Hazara Expatriates.n n Background:n n Declaration by the intellectuals from Afghanistan in support of the &ldquo;Enlightening movement&rdquo;.n n May 8, 2016n n Translated by Hazara People International Networkn n In the name of God of wisdom and enlightenmentn.';

$data2 = 'n            Provicial Council Uruzgan 8 Members 20090820 Elections:Mohammad Aman Hotak Amanullah Hotaki was the PC Chief (20110114). He was replaced by Ibrahim Akhunzada Januar 2012. who accused his predecessor of misappropriating the council’s budget. Akhunzada escaped unhurt in a roadside bombing in Dehrawud District, Uruzgan province on 20121030.nnnnnnnnnnnnBiographies of Uruzgan provincial council membersnnnnnn1-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Amanullah Hotaki: Amanullah Hotaki is the son of Malik Gulam Jan. He is born in 1981 at Nawabad village of Dihrawud district..6-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Jan Mohammad Karimi: Jan Mohammad Karimi is the son of Alhaj Tal. He is born in 1977 in Dazak village of Dihrawud district.He studied up to twelfth class but has no political affiliation.&nbsp;nnnnnnnnnnnnn';

$data3 = 'n 1. Chairman Afghanistan Geodesy and Cartography AGCHO: Eng. Abdul Raouf Yari (20080503)nalso in Afghanistan Geodesy also Cartography: Eng. Abd. Wasi, Amanullah Afshar (20091012)nHead of Department of Geography:Prof. Mohammad Zarif Taniwal (20091012)';

$data4 = 'n n 20. Balkh: has 11 seats including three for women. The elected candidates represent a total of 97,727 votes.nn n n n n Non ';

$data_fixed = no_single_function_worked_on_all_4_examples($data);
echo data_fixed;
?>

So I want to clean up the beginning spacing of n, and the ones at the end. So that the string starts and ends with just nothing, and the spacing of n in middle of content stay intact..

So that result would be like this:

$data = 'Member of the public council of Enlightening Movement Enlightenment Movementn Fakori Beheshti (20160517)n MP Raihana Azad (20170910)n n The &quot;Enlightening movement&quot; is a Hazara controlled social movement promoting Hazara affairs in Afghanistan. It has international supporters mostly Hazara Expatriates.n n Background:n n Declaration by the intellectuals from Afghanistan in support of the &ldquo;Enlightening movement&rdquo;.n n May 8, 2016n n Translated by Hazara People International Networkn n In the name of God of wisdom and enlightenment';
$data2 = 'Provicial Council Uruzgan 8 Members 20090820 Elections:Mohammad Aman Hotak Amanullah Hotaki was the PC Chief (20110114). He was replaced by Ibrahim Akhunzada Januar 2012. who accused his predecessor of misappropriating the council’s budget. Akhunzada escaped unhurt in a roadside bombing in Dehrawud District, Uruzgan province on 20121030.nnnnnnnnnnnnBiographies of Uruzgan provincial council membersnnnnnn1-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Amanullah Hotaki: Amanullah Hotaki is the son of Malik Gulam Jan. He is born in 1981 at Nawabad village of Dihrawud district..6-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Jan Mohammad Karimi: Jan Mohammad Karimi is the son of Alhaj Tal. He is born in 1977 in Dazak village of Dihrawud district.He studied up to twelfth class but has no political affiliation.&nbsp';

Please someone help me to write a function to parse these strings in that way. I can not figure out the PHP Logic to get it done, and removing all formatting is not an option 🙁

Debugging WordPress Plugin for Auto-Submitting Gravity Forms Every 30 Minutes

Hello fellow developers,

I’m working on a simple WordPress plugin designed to auto-submit a Gravity Forms form every 30 minutes using WP-Cron. However, the plugin doesn’t seem to be functioning as expected — the form is not being submitted automatically.

What the Plugin Should Do
Add a custom cron schedule to run every 30 minutes.
Use the Gravity Forms API to submit a specific form with predefined data.
Log any success or error messages for debugging purposes.
Issues Encountered
The scheduled task doesn’t appear to execute, and the form doesn’t submit as planned.
No errors are logged, even though I’ve enabled WP_DEBUG and checked the debug.log file.
Request
Could you please review the plugin code and help identify any potential issues? Here’s the complete plugin code:

<?php
/*
Plugin Name: Auto Submit Form Every 30 Minutes
Description: A simple plugin to auto-submit a specific Gravity Form every 30 minutes.
Version: 1.0
Author: Your Name
*/

// Prevent direct access to the file
if (!defined('ABSPATH')) {
    exit;
}

// Add a new cron schedule for every 30 minutes
add_filter('cron_schedules', 'asf_add_half_hour_schedule');
function asf_add_half_hour_schedule($schedules) {
    $schedules['half_hour'] = array(
        'interval' => 1800, // 30 minutes in seconds
        'display'  => __('Every 30 Minutes')
    );
    return $schedules;
}

// Function to auto-submit the form
function asf_auto_submit_form() {
    $form_id = 1; // ID of the form to submit

    // Form data as an array, with field IDs as keys
    $form_data = [
        1 => 'User Name',        // Example data for field ID 1
        2 => '[email protected]', // Example data for field ID 2
        3 => 'Sample description' // Example data for field ID 3
    ];

    // Submit form using Gravity Forms API
    $result = GFAPI::submit_form($form_id, $form_data);

    if (is_wp_error($result)) {
        error_log('Form submission error: ' . $result->get_error_message());
    } else {
        error_log('Form submitted successfully! Entry ID: ' . $result['entry_id']);
    }
}

// Schedule the cron job if not already scheduled
function asf_schedule_auto_submit() {
    if (!wp_next_scheduled('asf_auto_submit_form_event')) {
        wp_schedule_event(time(), 'half_hour', 'asf_auto_submit_form_event');
    }
}
add_action('wp', 'asf_schedule_auto_submit');

// Hook cron event to form submission function
add_action('asf_auto_submit_form_event', 'asf_auto_submit_form');

// Clear the scheduled task when the plugin is deactivated
function asf_clear_scheduled_auto_submit() {
    wp_clear_scheduled_hook('asf_auto_submit_form_event');
}
register_deactivation_hook(__FILE__, 'asf_clear_scheduled_auto_submit');

Troubleshooting Steps I’ve Tried
Enabled WP_DEBUG and WP_DEBUG_LOG to check for errors.
Used the WP Crontrol plugin to verify if the cron event is scheduled, but it doesn’t seem to run.
Checked permissions and verified that the Gravity Forms plugin is active.
If you spot anything that could be causing this issue or have suggestions on how to debug further, I’d greatly appreciate it! Thanks in advance for your help!

How can I show the error message only one time?

I am using PHP and JavaScript code on my WooCommerce website to display inline error messages on the wooocommerce checkout page.

Currently, the error message appears multiple times when any required field is empty due to a loop in the code. When I move the error handling code outside the loop, the message displays only once, but then the system does not redirect me to the payment page. I would like to show the error validation message “O o o p s, looks like some info is missing. Please fill in all *Required fields so we can complete your order” only once to ensure that I can still be redirected to the payment page.

PHP code:

add_action( 'woocommerce_after_checkout_form', 'add_custom_validation_script', 20 );

function add_custom_validation_script() {
    wp_enqueue_script(
        'inline_validation_script',
        get_stylesheet_directory_uri() . '/js/inline-validation.js',
        ['jquery']
    );
}

/**
 * adds error message field element to get inline error messages working
 * 
 * @param array $fields
 * @param object $errors
 */
add_filter( 'woocommerce_form_field', 'add_inline_error_messages_element', 10, 4 );

function add_inline_error_messages_element( $field, $key, $args, $value ) {
    if ( strpos( $field, '</span>' ) !== false ) {
        $error = '<span class="js-custom-error-message" style="display:none"></span>';
        $field = substr_replace( $field, $error, strpos( $field, '</span>' ), 0);
    }
    return $field;
}

/**
 * process custom checkout validations
 *
 * @param array $fields
 * @param object $errors
 */

add_action('woocommerce_after_checkout_validation', 'custom_checkout_validations', 10, 2);

function custom_checkout_validations($data, $errors){
    
    $your_custom_checkout_field = filter_input(INPUT_POST, 'your_custom_input_field');
    
    // your custom validations goes here
    // this loop adds a data array to all error messages which will be applied as a "data-error-for" HTML attribute
    // to read out the corresponding field ids with javascript and display the error messages inline
    foreach( $errors->errors as $original_key => $error ) {
        $field_key = $original_key;

        // filter and rewrite the field id for native woocommerce error messages with a key containing _required
        if(strpos($original_key, '_required') !== false) {
            $field_key = str_replace('_required','', $original_key);
            $error[0] = __('This is a required field', 'YourThemeName');
            
            if( !empty($errors->get_error_codes() ) ) {
                $errors->add( 'validation', 'O o o p s, looks like some info is missing. Please fill in all *Required fields so we can complete your order.' );
            }
        }
        
        // switch out the old error messages with the ones including a spiced up data array
        // to display with javascript
       $errors->remove($original_key);
       $errors->add($original_key, trim($error[0]), ['error-for' => $field_key . '_field']);
    }
}

JS code:

jQuery(function ($) {
    'use strict';

    addInlineMessages();

    // Implementation

    // Listen to js event
    $(document.body).on('updated_checkout', function() {
        addInlineMessages();
    });

    function addInlineMessages() {
        var woocommerceErrorsEl = $('.woocommerce-error');
        var woocommerceInlineErrorsEl = $('li[data-error-for]', woocommerceErrorsEl);
        var inlineErrorMessagesEl = $('.js-custom-error-message');

        // as we use ajax submitting hide old validation messages
        if(inlineErrorMessagesEl.length) {
            inlineErrorMessagesEl.hide();
        }

        if(woocommerceInlineErrorsEl.length) {
            woocommerceInlineErrorsEl.each(function () {
                var errorEl = $(this);
                var errorText = $.trim(errorEl.text());

                var targetFieldId = errorEl.data('error-for');

                if(errorText && targetFieldId) {
                    var targetFieldEl = $('#' + targetFieldId);
                    var errorMessageField = $('.js-custom-error-message', targetFieldEl);

                    if(targetFieldEl.length && errorMessageField.length) {
                        targetFieldEl.addClass('woocommerce-invalid');

                        errorMessageField.text(errorText);
                        errorMessageField.show();
                        errorEl.hide();
                    }
                }
            });

            if(woocommerceInlineErrorsEl.filter(':visible').length === 0) { 
                if(inlineErrorMessagesEl.filter(':visible').length > 0) {
                    scrollToElement(inlineErrorMessagesEl.filter(':visible').first());
                }
            } else {
                $('li:not([data-error-for])', woocommerceErrorsEl).hide();;
                scrollToElement(woocommerceErrorsEl);
            }
        }
    }

    function scrollToElement(el) {
        if(el.length) {
            $([document.documentElement, document.body]).animate({
                scrollTop: el.offset().top - 100
            }, 2000);
        }
    }

    // event listeners
    $(document.body).on('checkout_error', function (event) {
        jQuery('html, body').stop();

        addInlineMessages();
    });
});

How to Display Real-Time Progress Bar for Product Import in WooCommerce?

I am building a custom product import page for WooCommerce where users can upload a CSV file to update product stock or price. I want to show a real-time progress bar that displays the percentage of records updated, e.g., how much needs to be updated and how much has already been updated. I am using PHP for the backend processing and AJAX for handling the import asynchronously. The import process works, but I am struggling to display the progress dynamically to the user while the import is happening.

Additionally, I’m fetching products by their SKU, because when I try to fetch them by product ID, I encounter issues where the product ID seems to exist, but when I try to use it, I get errors saying that the product is invalid or cannot be found. Sometimes, Excel converts my SKU values to scientific notation, which causes problems when using them for product lookup.

How can I resolve both the issues of using the product ID correctly and displaying the progress bar in real-time?

// Add the custom menu for the import page
add_action('admin_menu', 'custom_import_menu');

function custom_import_menu() {
    add_submenu_page(
        'woocommerce',
        'Custom Product Import',
        'Product Import',
        'manage_options',
        'custom-product-import',
        'custom_product_import_page'
    );
}

function custom_product_import_page() {
    ?>
    <div class="wrap">
        <h1>Custom Product Import</h1>
        <form method="post" enctype="multipart/form-data" id="product_import_form">
            <label for="import_file">Choose CSV file (.csv):</label>
            <input type="file" name="import_file" id="import_file" accept=".csv">
            <input type="hidden" name="update_type" value="stock">
            <input type="submit" name="import_products" class="button button-primary" value="Import Products">
        </form>
        <div id="progress-bar-container"></div>
    </div>
    <?php
    if (isset($_POST['import_products']) && !empty($_FILES['import_file']['tmp_name'])) {
        $uploadedFile = $_FILES['import_file']['tmp_name'];

        // Move file to a temporary location
        $tempFilePath = wp_upload_dir()['basedir'] . '/temp_import_file.csv';
        move_uploaded_file($uploadedFile, $tempFilePath);

        custom_import_products_csv_preview($tempFilePath);
    }
}

// Function to show CSV preview
function custom_import_products_csv_preview($file) {
    if (($handle = fopen($file, "r")) !== FALSE) {
        $header = fgetcsv($handle, 1000, ",");
        $previewRows = [];
        for ($i = 0; $i < 10 && ($row = fgetcsv($handle, 1000, ",")) !== FALSE; $i++) {
            $previewRows[] = $row;
        }
        fclose($handle);

        $updateColumn = null;
        
        // Check for column names
        if (strtolower($header[3]) == 'stock') {
            $updateColumn = 'stock'; // Use stock column for update
        } elseif (strtolower($header[2]) == 'price') {
            $updateColumn = 'price'; // Use price column if it exists
        }

        if (!$updateColumn) {
            echo '<div class="error notice"><p>Second column should be "Price" or "Stock" to indicate the update type. Ensure the correct column is used for the update.</p></div>';
            return;
        }

        echo '<div class="notice notice-info"><p>Detected ' . ucfirst($updateColumn) . ' column. Here is a preview of the data:</p></div>';
        echo '<table class="wp-list-table widefat fixed striped">';
        echo '<thead><tr><th>SKU</th><th>' . ucfirst($updateColumn) . '</th></tr></thead>';
        echo '<tbody>';
        foreach ($previewRows as $row) {
            echo '<tr><td>' . esc_html($row[2]) . '</td><td>' . esc_html($row[3]) . '</td></tr>';
        }
        echo '</tbody></table>';
        ?>
        <form method="post" action="">
            <input type="hidden" name="confirm_import" value="1">
            <input type="hidden" name="update_type" value="<?php echo esc_attr($updateColumn); ?>">
            <input type="hidden" name="file_path" value="<?php echo esc_attr($file); ?>">
            <input type="submit" name="confirm_update" class="button button-primary" value="Confirm Update">
        </form>
        <?php
    } else {
        echo '<div class="error notice"><p>Failed to open the CSV file. Please check the file format.</p></div>';
    }
}

add_action('wp_ajax_process_product_import', 'process_product_import');

function process_product_import() {
    if (!isset($_FILES['import_file'])) {
        wp_send_json_error(['message' => 'No file uploaded']);
    }

    $file = $_FILES['import_file'];
    $updateType = $_POST['update_type'];

    // Process the file
    $uploadedFile = $file['tmp_name'];
    if (($handle = fopen($uploadedFile, "r")) !== FALSE) {
        fgetcsv($handle, 1000, ","); // Skip header row
        $totalRows = count(file($uploadedFile)) - 1; // Total rows excluding header
        $updatedCount = 0;

        // Loop through the rows and update products
        while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
            $sku = sanitize_text_field($row[2]);
            $value = floatval($row[3]);
            $product = get_product_by_sku($sku);

            if ($product) {
                if ($updateType == 'stock') {
                    $product->set_stock_quantity($value);
                    $product->set_manage_stock(true);
                    $product->save();
                    $updatedCount++;
                }
            }

            // Send progress update (percentage)
            $progress = ($updatedCount / $totalRows) * 100;
            wp_send_json_success(['progress' => $progress]);
        }
        fclose($handle);
    }

    wp_send_json_success(['message' => 'Import completed successfully.']);
}

// Function to retrieve the product by SKU
function get_product_by_sku($sku) {
    global $wpdb;

    $product_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_sku' AND meta_value='%s' LIMIT 1", $sku ) );

    if ( $product_id ) {
        return new WC_Product( $product_id );
    }

    return null;
}

I tried using the wp_send_json_success() function to send progress updates during the import process, and I also included a progress bar element in the HTML. However, the progress bar does not update in real time, and the page reloads instead of dynamically updating the progress. I expected that the progress bar would show the ongoing progress as the product stock or price is updated based on the CSV file’s content.

PHP Sum up fields [duplicate]

I have following multidimensional array in PHP and want to clean it up but also sum up the fields.

Example:

    [UP-IXSZ-RP36] => Array
        (
            [stueck] => 1
            [anzahl] => 1
            [stock] => H-11-004
            [name] => Coffee Mate Original
        )

    [PW-KQZA-ROHD] => Array
        (
            [stueck] => 4
            [anzahl] => 1
            [stock] => H-14-017
            [name] => Trumpf AK
        )

    [K3-9SV1-MQQO] => Array
        (
            [stueck] => 5
            [anzahl] => 1
            [stock] => H-14-017
            [name] => Trumpf AK
        )

    [EN-6BZL-HJIG] => Array
        (
            [stueck] => 1
            [anzahl] => 1
            [stock] => B
            [name] => Turm Sahne
        )

    [3M-EEF4-JO4N] => Array
        (
            [stueck] => 1
            [anzahl] => 1
            [stock] => H-14-017
            [name] => Trumpf AK
        )

I want to filter by name and it should then show me following array.
Which SKU he uses is not important.

    [UP-IXSZ-RP36] => Array
        (
            [stueck] => 1
            [anzahl] => 1
            [stock] => H-11-004
            [name] => Coffee Mate Original
        )

    [PW-KQZA-ROHD] => Array
        (
            [stueck] => 10
            [anzahl] => 1
            [stock] => H-14-017
            [name] => Trumpf AK
        )

    [EN-6BZL-HJIG] => Array
        (
            [stueck] => 1
            [anzahl] => 1
            [stock] => B
            [name] => Turm Sahne
        )

Can someone help me with this issue?

Thanks.

How to exclude empty tags exporting orders as XML file?

I am using PHP code in the plugin WP ALL EXPORT PRO to filter out specific orders from WooCommerce that contain relevant products with relevant details & options and then export them via XML / FTP to my fulfillment partner.

The values for details & options are different for each product. Therefore I need a code snippet to generally exclude empty tags when exporting in the XML file (Concerning the pink marked area in overview below).

How to exclude empty tags

USED CURRENT PHP CODE. THE SECTION //add options to the output IS TO BE CONSIDERED

<?php
    function my_get_order_items( $order_id ) {
        $order = wc_get_order( absint($order_id) ); // Get the WC_Order object
    
        if ( ! is_a($order, 'WC_Order') ) {
            return false; // Exit if not an order
        }
        $order_details = ""; // Initialize variable as string to store order details
    
        // Loop through order items
        foreach ( $order->get_items() as $item ) {
            if ( ! ( strpos($item->get_name(), 'KERAMIKTASSE') !== false
            || strpos($item->get_name(), 'BAUMWOLLTASCHE') !== false
            || strpos($item->get_name(), 'SWEATSHIRT') !== false
            || strpos($item->get_name(), 'HOODIE') !== false
            || strpos($item->get_name(), 'T-SHIRT') !== false ) ) { 
                continue; 
            }
            $product    = $item->get_product(); // Get the product object
            $product_id = $item->get_product_id(); // Get the product object
    
            $order_details .= "**LT**item**GT**";
            $order_details .= "**LT**ID**GT**" . $product->get_sku() . "**LT**/ID**GT**";
            $order_details .= "**LT**produktname**GT**" . $item->get_name() . "**LT**/produktname**GT**";
            $order_details .= "**LT**amount**GT**" . $item->get_quantity() . "**LT**/amount**GT**";
            $order_details .= "**LT**upload**GT**" . maybe_serialize( get_field( 'upload', $product_id ) ) . "**LT**/upload**GT**";
            $order_details .= "**LT**size**GT**" . maybe_serialize( get_field( 'size', $product_id ) ) . "**LT**/size**GT**";
            $order_details .= "**LT**groesse**GT**" . $product->get_attribute('pa_groesse')  . "**LT**/groesse**GT**";
            $order_details .= "**LT**material**GT**" . maybe_serialize( get_field( 'material', $product_id ) ) . "**LT**/material**GT**";
            $order_details .= "**LT**print**GT**" . maybe_serialize( get_field( 'print', $product_id ) ) . "**LT**/print**GT**";
            $order_details .= "**LT**variante**GT**" . maybe_serialize( get_field( 'variante', $product_id ) ) . "**LT**/variante**GT**";
            $order_details .= "**LT**category**GT**" . maybe_serialize( get_field( 'category', $product_id ) ) . "**LT**/category**GT**";
    
            //add options to the output
            $order_details .= "**LT**Options**GT**";
            $order_details .= "**LT**Option**GT****LT**ID**GT**" . maybe_serialize( get_field( 'groupid_115', $product_id ) ) . "**LT**/ID**GT****LT**Value**GT**" . maybe_serialize( get_field( 'value_115', $product_id ) ) . "**LT**/Value**GT****LT**/Option**GT**";
            $order_details .= "**LT**Option**GT****LT**ID**GT**" . maybe_serialize( get_field( 'groupid_117', $product_id ) ) . "**LT**/ID**GT****LT**Value**GT**" . maybe_serialize( get_field( 'value_117', $product_id ) ) . "**LT**/Value**GT****LT**/Option**GT**";
            $order_details .= "**LT**Option**GT****LT**ID**GT**" . maybe_serialize( get_field( 'groupid_118', $product_id ) ) . "**LT**/ID**GT****LT**Value**GT**" . maybe_serialize( get_field( 'value_118', $product_id ) ) . "**LT**/Value**GT****LT**/Option**GT**";
            $order_details .= "**LT**/Options**GT**";
            $order_details .= "**LT**/item**GT**";
        }
        return $order_details;
    }
?>

laravel project on apache

I have a system built in Laravel, the system tries to perform an INCLUDE to a certain file using a server variable, the variable returns the following path /home/someuser/…. I get an error in PHP that the file is not found, even though it is found, when I tried to enter the folder path of the file via FTP, I found the file and everything OK when the routing was
/DOMAIN/…
But when the path is /home/someuser/domain.
I am getting that the file is not found. I realized that it is a problem with promission access, probably to the home folder and to the user’s folder. How can I fix this?

this is the error i am getting

require(/home/affy/domains/****/public_html/vendor/itstructure/laravel-multi-menu/src/../config/multimenu.php): Failed to open stream: No such file or directory

i try to change /home to 777 and /home/affy to 777
i change the ftp setting to allow user outside is folder and now i can get to /home from ftp but i still getting an error

How to ensure that only one order is exported per XML FILE?

I am using an export plugin to filter out specific orders from WooCommerce containing relevant products with relevant details & options and then export them via XML / FTP to my fulfillment partner.

PROBLEM:
Currently, not every order is exported individually as an XML file, but several are combined in one XML output.

What do I have to change in my existing code so that only one order is exported individually per XML export?

SEE OVERVIEW BELOW:

Overview: Code and XML Output

The plugin is based on an XML FUNCTION SECTION
with the following code:

<?xml version="1.0" encoding="UTF-8"?>
<order>
    <!-- BEGIN LOOP -->
        <commission>{Bestell ID}</commission>
        <production>1</production>

        <receiver>
            <line1>{Shipping First Name} {Shipping Last Name}</line1>
            <line2>{Shipping Company}</line2>
            <street>{Shipping Address 1}</street>
            <streetnumber>{Shipping Address 2}</streetnumber>
            <country_code>{Shipping Country}</country_code>
            <zip>{Shipping Postcode}</zip>
            <city>{Shipping City}</city>
            <email>{Customer Account Email Address}</email>

        </receiver> 

        <items> 
            [my_get_order_items({Bestell ID})]
        </items>
    <!-- END LOOP -->
</order>

IMPORTANT! This structure is predefined by the plugin:

<?xml version=“1.0” encoding=“UTF-8”?>

Title tag

<!-- BEGIN LOOP -->

<!-- END LOOP -->

Footer tag

AND INDIVIDUAL PHP CODE SECTION:

<?php

function my_get_order_items( $order_id ) {
    $order = wc_get_order( absint($order_id) ); // Get the WC_Order object
    
    if ( ! is_a($order, 'WC_Order') ) {
        return false; // Exit if not an order
    }
    $order_details = ""; // Initialize variable as string to store order details

    // Loop through order items
    foreach ( $order->get_items() as $item ) {
        if ( ! ( strpos($item->get_name(), 'KERAMIKTASSE') !== false
        || strpos($item->get_name(), 'BAUMWOLLTASCHE') !== false
        || strpos($item->get_name(), 'SWEATSHIRT') !== false
        || strpos($item->get_name(), 'HOODIE') !== false
        || strpos($item->get_name(), 'T-SHIRT') !== false ) ) { 
            continue; 
        }
        $product    = $item->get_product(); // Get the product object
        $product_id = $item->get_product_id(); // Get the product object

        $order_details .= "**LT**item**GT**";
        $order_details .= "**LT**ID**GT**" . $product->get_sku() . "**LT**/ID**GT**";
        $order_details .= "**LT**produktname**GT**" . $item->get_name() . "**LT**/produktname**GT**";
        $order_details .= "**LT**amount**GT**" . $item->get_quantity() . "**LT**/amount**GT**";
        $order_details .= "**LT**upload**GT**" . maybe_serialize( get_field( 'upload', $product_id ) ) . "**LT**/upload**GT**";
        $order_details .= "**LT**size**GT**" . maybe_serialize( get_field( 'size', $product_id ) ) . "**LT**/size**GT**";
        $order_details .= "**LT**groesse**GT**" . $product->get_attribute('pa_groesse')  . "**LT**/groesse**GT**";
        $order_details .= "**LT**material**GT**" . maybe_serialize( get_field( 'material', $product_id ) ) . "**LT**/material**GT**";
        $order_details .= "**LT**print**GT**" . maybe_serialize( get_field( 'print', $product_id ) ) . "**LT**/print**GT**";
        $order_details .= "**LT**variante**GT**" . maybe_serialize( get_field( 'variante', $product_id ) ) . "**LT**/variante**GT**";
        $order_details .= "**LT**category**GT**" . maybe_serialize( get_field( 'category', $product_id ) ) . "**LT**/category**GT**";

        //add options to the output
        $order_details .= "**LT**Options**GT**";
        if(get_field( 'groupid_115', $product_id )) {             
        $order_details .= "**LT**Option**GT****LT**ID**GT**" . maybe_serialize( get_field( 'groupid_115', $product_id ) ) . "**LT**/ID**GT****LT**Value**GT**" . maybe_serialize( get_field( 'value_115', $product_id ) ) . "**LT**/Value**GT****LT**/Option**GT**"; }
        
        if(get_field( 'groupid_117', $product_id )) {             
            $order_details .= "**LT**Option**GT****LT**ID**GT**" . maybe_serialize( get_field( 'groupid_117', $product_id ) ) . "**LT**/ID**GT****LT**Value**GT**" . maybe_serialize( get_field( 'value_117', $product_id ) ) . "**LT**/Value**GT****LT**/Option**GT**"; }
        
        if(get_field( 'groupid_118', $product_id )) {             
            $order_details .= "**LT**Option**GT****LT**ID**GT**" . maybe_serialize( get_field( 'groupid_118', $product_id ) ) . "**LT**/ID**GT****LT**Value**GT**" . maybe_serialize( get_field( 'value_118', $product_id ) ) . "**LT**/Value**GT****LT**/Option**GT**"; }
        
    }
    
    return $order_details;
}

?>

How can I ensure that only one order is exported per XML file?

Creating phonepe payment gateway using phonepe checkout.js but it is failed to initiate payments [closed]

I am creating creating phonepe integration but failed to intiate payment, I am getting messages like Payment Initiation failed

My front code is:

document.getElementById("payWithPhonePe").addEventListener("click", function() {
  alert("hi");
  const amount = 15;
  const orderId = "unique-order-id-" + new Date().getTime();
  fetch("<?php echo site_url("beta/change_package_1/create_phonePe"); ?>", {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        amount: amount,
        orderId: orderId
      })
    }).then(response => response.json()).then(data => {
    if (data.success) {
      PhonePe.init({
        orderId: data.data.orderId,
        merchantId: data.data.merchantId,
        redirectUrl: data.data.redirectUrl,
        success: (res) => {
          alert("Payment was successful!");
          console.log(res);
        },
        failure: (res) => {
          alert("Payment failed.");
          console.log(res);
        },
        close: () => {
          alert("Payment window closed.");
        }
      });
    } else {
      alert("Payment initiation failed!");
    }
  }).catch(error => {
    // console.error("Error:", error);      
  });
});
<script src="https://mercury.phonepe.com/web/bundle/checkout.js"></script>

<button id="payWithPhonePe">Pay with PhonePe</button>

Backend code is: Controller.php
method is:

function createPhonePePayment($amount, $orderId) {
        $merchantId = "";
        $merchantKey = "";
    
        $url = "https://api.phonepe.com/apis/hermes/pg/v1/pay";
        // Payment request payload
        $payload = [
            "merchantId" => $merchantId,
            "transactionId" => $orderId,
            "amount" => $amount * 100,
            "currency" => "INR",
            "redirectUrl" => site_url('beta/change_package_1')
        ];
    
        $jsonPayload = json_encode($payload);
    
        $checksum = hash_hmac('sha256', $jsonPayload, $merchantKey);
    
        $headers = [
            'Content-Type: application/json',
            'X-VERIFY: ' . $checksum . "###" . $merchantId,
        ];
    
        // Initialize cURL
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonPayload);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
        // Execute the request
        $response = curl_exec($ch);
        curl_close($ch);
    
        // Decode the response
        return json_decode($response, true);
    }

    public function create_phonePe(){
        header('Content-Type: application/json');
        $input = json_decode(file_get_contents("php://input"), true);
        if (!isset($input['amount']) || !isset($input['orderId'])) {
            echo json_encode(["success" => false, "error" => "Invalid input."]);
            return;
        }
    
        $amount = $input['amount'];
        $orderId = $input['orderId'];
        $responseData = $this->createPhonePePayment($amount, $orderId);
        
        if ($responseData && isset($responseData['data']['instrumentResponse']['redirectUrl'])) {
            echo json_encode([
                "success" => true,
                "data" => [
                    "orderId" => $orderId,
                    "merchantId" => $merchantId,
                    "redirectUrl" => $responseData['data']['instrumentResponse']['redirectUrl']
                ]
            ]);
        } else {
            echo json_encode([
                "success" => false,
                "error" => isset($responseData['error']) ? $responseData['error'] : "Failed to initiate payment."
            ]);
        }
    }

Please help me solve the problem. I am using right credentials like merchant Id and API key. I want to solve phonepe integration payments initiation failed problem.

How to attach Referer in the PDF which is generated using mPDF library

As I am generating a PDF using mPDF library. My concern is that, the PDF contains the assets (like images), these images having the domain restriction (i.e. no one can access these assets directly, these assets are accessed only from the specified domain).
So when I add these assets in the PDF’s html body, these assets get blocked (i.e. they are not get displayed).

Can this problem be solved by attaching the referer to the PDF?

ApiPlatform generates invalid IRI (without ID) when using State Provider

I have a User entity in API Platform and created a custom operation to return information about the currently logged-in user, using a state provider.

ApiResource tag:

#[ApiResource(
  operations: [
    new Get(
      uriTemplate: '/user',
      normalizationContext: ['groups' => ['user:read']],
      security: self::SECURITY_GET,
      provider: UserStateProvider::class
    )
]

UserStateProvider:

class UserStateProvider implements ProviderInterface
{
    public function __construct(
        private readonly Security $security,
    ) {}

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
    {
        return $this->security->getUser();
    }
}

The problem: This endpoint returns an IRI without an ID, which looks like this:

"@context": "/api/contexts/User",
"@id": "/api/user",
"@type": "User",

I attempted to fetch the user from the repository within UserStateProvider, but it did not resolve the issue:

$user = $this->security->getUser();
return $user ? $this->userRepository->find($user->getId()) : null;

Adding annotation to signed pdf using PHP with fpdf and tcpdf removes signature

I’m trying to add a page with an annotation box to an existing signed pdf. This should be possible with TCPDF and FPDF. Unfortunately, it removes the sign and the pdf cannot be validated after being altered. The displayed pdf looks the same, though.

The code (generated by AI) follows:

<?php
use FpdfFpdf;
use setasignFpdiFpdi;

require_once '../lib/fpdf/Fpdf.php';
require_once '../lib/tcpdf/tcpdf.php';
require_once '../lib/fpdi/src/autoload.php';

// require_once '../vendor/autoload.php';

$fpdf = new FPDFFPDF();

$pdf = new Fpdi();

$pdf->setSourceFile('test-form-signed.pdf');

// Loop through the pages of the original PDF
$pageCount = $pdf->setSourceFile('test-form-signed.pdf');
for ($i = 1; $i <= $pageCount; $i++) {
    $tplId = $pdf->importPage($i);
    $pdf->addPage();
    $pdf->useTemplate($tplId, 0, 0);
}

// Add a blank new page at the end
$pdf->AddPage();

// Set annotation properties
$pdf->SetFont('Helvetica', '', 12);
$pdf->SetTextColor(0, 0, 0);
$pdf->Text(10, 10, "This is a text annotation on a new blank page.");

// Save the output PDF
$pdf->Output('F', 'test-form-annotated-signed.pdf');

The test-form-annotated-signed.pdf is about half the size of the original file and it no longer passes a validation test. Probably, the signature/certificate was removed during the process.

By the way, the pdf is signed with a OCES-3 certificate issued by the State of Denmark.

Please note that solutions that involve using Adobe Acrobat, Signicat etc. are not an option.

Laravel: (Job dispatch) Failed to open stream: Permission denied

fopen(app/storage/framework/cache/data/6a/e8/6ae8f7a027ae2ffc516a3933fcade51ab014d34d): Failed to open stream: Permission denied

Stack trace

app/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:256
app/vendor/laravel/framework/src/Illuminate/Filesystem/LockableFile.php:69
app/vendor/laravel/framework/src/Illuminate/Filesystem/LockableFile.php:42
app/vendor/laravel/framework/src/Illuminate/Cache/FileStore.php:108
app/vendor/laravel/framework/src/Illuminate/Cache/FileLock.php:14
app/vendor/laravel/framework/src/Illuminate/Cache/Lock.php:91
app/vendor/laravel/framework/src/Illuminate/Bus/UniqueLock.php:43
app/vendor/laravel/framework/src/Illuminate/Foundation/Bus/PendingDispatch.php:164
app/vendor/laravel/framework/src/Illuminate/Foundation/Bus/PendingDispatch.php:188
app/vendor/ssntpl/cloud-storage/src/CloudStorageAdapter.php:65
app/vendor/ssntpl/cloud-storage/src/CloudStorageAdapter.php:151

I am dispatching job app/vendor/ssntpl/cloud-storage/src/CloudStorageAdapter.php:65
job

SyncFileJob::dispatch($path, $fromDisk, $remoteDisk)->onConnection($this->connection)->onQueue($this->queue);

then sometimes that line throw above error(Failed to open stream: Permission denied) whereas sometimes it working fine.

can anyone explain me, why is it happened?
what will be the solution for it?

If there was a permission issue then not a single job would be run.
queue connection is sync