• Resolved alexinwp

    (@alexinwp)


    Hi,

    I use Stylemix’s Cost Calculator Builder plugin so customers can calculate and order custom products.

    Obviously, I also use PDF Invoices & Packing Slips for WooCommerce and I’d like the details (length, width, height, etc.) of a custom item to be displayed on invoices and packing slips, just like they are on the shopping cart page.

    I tried adding the following code to a custom template-functions file, without success:

    add_action( 'wpo_wcpdf_after_item_meta', 'wpo_wcpdf_product_custom_field', 10, 3 );
    function wpo_wcpdf_product_custom_field ( $template_type, $item, $order ) {
    // check if product exists first
    if (empty($item['product'])) return;

    $field_name = 'meta_data[ccb_calculator]';
    $details = $item['product']->get_meta($field_name,true,'edit');
    if (!empty($details)) {
    echo '<div class="product-details">Details: '.$details.'</div>';
    }
    }

    I also tried using subfields of the calculator (e.g., [quantity_field_id_0] for length). That didn’t work either.

    Is the code incorrect or is it impossible to display these custom metadatas in invoices/packing slips ?

Viewing 11 replies - 1 through 11 (of 11 total)
  • Plugin Contributor Darren Peyou

    (@dpeyou)

    Hey @alexinwp,

    My very first thought is that this line seems odd to me:

     $field_name = 'meta_data[ccb_calculator]';

    I do not think that is correct custom field usage. I would expect this instead:

     $field_name = 'ccb_calculator';

    Could you replace the line I mentioned and retry?

    If that does not work, I recommend making sure that the custom field name you are using (ccb_calculator) is correct by following our documentation here:

    Finding WooCommerce Custom Fields – WP Overnight documentation

    This will help you either:
    – Find the correct custom field name.
    – Find the correct custom field structure (it could be embedded in another custom field).

    I myself am doubting that “ccb_calculator” is the name of the custom field you want to use, upon scanning the plugin code (but I could be wrong).

    Please share your findings, they will help us all. πŸ™‚

    Thread Starter alexinwp

    (@alexinwp)

    Hey Darren,

    Thanks for your reply. It seemed odd to me too (that’s what Store Toolkit displays though), but it didn’t work without the brackets either.

    Now it does “work” if I put if (empty($item['item'])) return; instead of if (empty($item['product'])) return; on the previous line.

    This way, it displays “Details: Array” below the product.

    According to Store Toolkit, [ccb_calculator] is an array of four items, including [calc_data], which is an array storing each customization option for my products (with another array containing individual labels and values). This is structured as follows :

    ccb_calculator 
    | calc_data
    | quantity_field_id_0
    | label
    | value
    | quantity_field_id_1
    | label
    | value

    This is the tricky part for me because I don’t really know PHP.

    How can I display my customization options (label + value) within a “Details” list ?

    Thank you in advance !

    Plugin Contributor Darren Peyou

    (@dpeyou)

    @alexinwp,

    Now it does β€œwork” if I put if (empty($item['item'])) return; instead of if (empty($item['product'])) return; on the previous line.


    I believe the reason your change returned some data is because you need to fetch the meta data of the woocommerce order item object (WC_Order_Item) instead of the meta data of the woocommerce product object (WC_Order_Item_Product). Your custom data would be attached to the order item in this case.

    I am still convinced that ccb_calculator is the correct field name, instead of meta_data[ccb_calculator]. I am not so sure why the Store Toolkit plugin displays it like that, but it has lead me to making the same mistake in the past. Supposedly, it is because the Store Toolkit plugin is showing the “data path” instead of the name of the woocommerce custom field.

    We likely need to update the documentation to address that.

    Since ccb_calculator is an array, you need to loop through the array to reach the data you want. The looping is done by the foreach part in the code below.

    Give this snippet a try:

    add_action( 'wpo_wcpdf_after_item_meta', 'wpo_wcpdf_ccb_calculator_details', 10, 3 );

    function wpo_wcpdf_ccb_calculator_details( $template_type, $item, $order ) {
    if ( ! $item instanceof WC_Order_Item ) {
    return;
    }

    $ccb_calculator = $item->get_meta( 'ccb_calculator', true, 'edit' );

    if (
    ! is_array( $ccb_calculator )
    || empty( $ccb_calculator['calc_data'] )
    || ! is_array( $ccb_calculator['calc_data'] )
    ) {
    return;
    }

    echo '<div class="product-details">';
    echo '<strong>Details:</strong>';
    echo '<ul>';

    foreach ( $ccb_calculator['calc_data'] as $option ) {
    $label = $option['label'] ?? '';
    $value = $option['value'] ?? '';

    if ( $label === '' && $value === '' ) {
    continue;
    }

    echo '<li>';
    echo esc_html( $label );

    if ( $label !== '' && $value !== '' ) {
    echo ': ';
    }

    echo esc_html( $value );
    echo '</li>';
    }

    echo '</ul>';
    echo '</div>';
    }

    Disclaimer: I have not tested this code myself.
    I am convinced it should work though.

    Plugin Contributor Darren Peyou

    (@dpeyou)

    Hey @alexinwp,

    Were you able to solve your issue with the last shared code snippet?

    Thread Starter alexinwp

    (@alexinwp)

    Hey Darren,

    Sorry for the late reply, I’ve been busy with other things and haven’t had time to test it.

    Thanks for the snippet and explanation. Unfortunately, it doesn’t work… Nothing else is displayed.

    Plugin Contributor Darren Peyou

    (@dpeyou)

    @alexinwp that’s unfortunate, sorry. πŸ™

    I think I found my error however (or at least 1 error). In this block of code:

       if ( ! $item instanceof WC_Order_Item ) {
    return;
    }

    I believe I’m supposed to use $item['item'] instead of just $item. A previous code adjustment you made (here) should even confirm this. So it is supposed to be:

    if ( ! $item['item'] instanceof WC_Order_Item ) {
    return;
    }

    So try this code snippet instead:

    add_action( 'wpo_wcpdf_after_item_meta', 'wpo_wcpdf_ccb_calculator_details', 10, 3 );

    function wpo_wcpdf_ccb_calculator_details( $template_type, $item, $order ) {
    if ( ! $item['item'] instanceof WC_Order_Item ) {
    return;
    }

    $ccb_calculator = $item->get_meta( 'ccb_calculator', true, 'edit' );

    if (
    ! is_array( $ccb_calculator )
    || empty( $ccb_calculator['calc_data'] )
    || ! is_array( $ccb_calculator['calc_data'] )
    ) {
    return;
    }

    echo '<div class="product-details">';
    echo '<strong>Details:</strong>';
    echo '<ul>';

    foreach ( $ccb_calculator['calc_data'] as $option ) {
    $label = $option['label'] ?? '';
    $value = $option['value'] ?? '';

    if ( $label === '' && $value === '' ) {
    continue;
    }

    echo '<li>';
    echo esc_html( $label );

    if ( $label !== '' && $value !== '' ) {
    echo ': ';
    }

    echo esc_html( $value );
    echo '</li>';
    }

    echo '</ul>';
    echo '</div>';
    }

    If the correction above does not work, here are my troubleshooting steps…

    • Could you tell me how much info is being displayed?
      For example: Does the text “Details:” appear?
      This helps me find the conditions I entered in the code snippet that is failing.
    • Under this line of code:
        $ccb_calculator = $item->get_meta( 'ccb_calculator', true, 'edit' );

    Could you add this?

    var_dump( $ccb_calculator );

    Save the snippet, then check the PDF output to see if something gets printed and what the printed value is.

    Thread Starter alexinwp

    (@alexinwp)

    No problem mate.

    The first correction got me a parse error message. The second one does nothing.

    Could this be because we’re not explicitly naming each option contained in calc_data that we want to display ?

    Plugin Contributor Darren Peyou

    (@dpeyou)

    @alexinwp,

    Could this be because we’re not explicitly naming each option contained in calc_data that we want to display ?

    I am not quite sure of that. The “Details:” text is outside and before the calc_data loop. Since the “Details:” text is not even visible, then I am more immediately inclined to think one of these two conditions is failing.
    if ( ! $item['item'] instanceof WC_Order_Item ) {
    return;
    }

    OR

      if (
    ! is_array( $ccb_calculator )
    || empty( $ccb_calculator['calc_data'] )
    || ! is_array( $ccb_calculator['calc_data'] )
    ) {
    return;
    }

    Hopefully this is not too advanced/complex:

    Were you able to perform this troubleshooting step? I forgot to add one step at the end:

    • Under this line of code:
        $ccb_calculator = $item->get_meta( 'ccb_calculator', true, 'edit' );

    Could you add this?

    var_dump( 'The custom field: ', $ccb_calculator );

    Finally, temporarily output your PDF as HTML in order to see the result of the var_dump( $ccb_calculator ) function.

    Path: WooCommerce > PDF Invoices > Advanced > Settings > Output to HTML.

    The data you would be looking for is anything that appears after the “The custom field: ” text.

    If there is no result at all, no printed text from the snippet in the item meta data area, then the 1st condition may be the condition that is failing. If “The custom field: ” text appears, then the 1st condition is not failing.

    Thread Starter alexinwp

    (@alexinwp)

    So there’s no printed text when I do it, but a “Fatal error: Call to a member function get_meta() on array” on the HTML output.

    I also tried $ccb_calculator = $item['item']->get_meta( 'ccb_calculator', true, 'edit' ); instead of $ccb_calculator = $item->get_meta( 'ccb_calculator', true, 'edit' );.

    It removes all the order details (items, quantities, prices and totals) on the settings preview mode. On the HTML output though, all the details are here, I also got a big mess of arrays, labels, values and calculations AND my details list correctly displayed as expected.

    I’m not sure if it’s worth mentioning, but the big mess of data includes the first options in the ccb_calculator array : product_id, item_name and order_id, before the calc_data array which contains the interesting options. It starts like that :

    array(6) { ["product_id"]=> int(34) ["item_name"]=> string(0) "" ["order_id"]=> int(0) ["calc_data"]=> array(14) { ["quantity_field_id_0"]=> array(2) { ["label"]=> string(12) "Longueur (L)" ["value"]=> string(6) "630 mm" }
    Plugin Contributor Darren Peyou

    (@dpeyou)

    @alexinwp,

    Your $item to $item['item'] correction helped a lot. The diagnostic step was successful thanks to that. We will not need HTML mode anymore. πŸ™‚

    The fact that you got a big mess of the data printed after the correction means that the 2nd condition was what was failing, as I had missed another incorrect usage of $item, on this line:

    $ccb_calculator = $item->get_meta( 'ccb_calculator', true, 'edit' );

    This caused a fatal error because I was applying the get_meta() function on the $item array object. We want that function on the WooCommerce order item object, so on $item['item'].

    This is the updated code snippet, with the above correction applied. I removed the var_dump()function, so you should not get an ugly printed mess anymore and the table items will return:

    add_action( 'wpo_wcpdf_after_item_meta', 'wpo_wcpdf_ccb_calculator_details', 10, 3 );

    function wpo_wcpdf_ccb_calculator_details( $template_type, $item, $order ) {
    if ( ! $item['item'] instanceof WC_Order_Item ) {
    return;
    }

    $ccb_calculator = $item['item']->get_meta( 'ccb_calculator', true, 'edit' );

    if (
    ! is_array( $ccb_calculator )
    || empty( $ccb_calculator['calc_data'] )
    || ! is_array( $ccb_calculator['calc_data'] )
    ) {
    return;
    }

    echo '<div class="product-details">';
    echo '<strong>Details:</strong>';
    echo '<ul>';

    foreach ( $ccb_calculator['calc_data'] as $option ) {
    $label = $option['label'] ?? '';
    $value = $option['value'] ?? '';

    if ( $label === '' && $value === '' ) {
    continue;
    }

    echo '<li>';
    echo esc_html( $label );

    if ( $label !== '' && $value !== '' ) {
    echo ': ';
    }

    echo esc_html( $value );
    echo '</li>';
    }

    echo '</ul>';
    echo '</div>';
    }
    • This reply was modified 3 weeks, 1 day ago by Darren Peyou. Reason: additional info
    Thread Starter alexinwp

    (@alexinwp)

    Your $item to $item['item'] correction helped a lot. The diagnostic step was successful thanks to that.

    I’m glad I did something… πŸ™‚

    Thank you so much for your help and your time, it works perfectly now.

    Take care.

Viewing 11 replies - 1 through 11 (of 11 total)

You must be logged in to reply to this topic.