1

So I'm attempting to create a custom FieldType for Freeform for a custom one-off application. Basically I have multiple hidden fields to populate data associated with a regular user input field.

I've been struggling with this for a while and don't know of a better way, so if someone knows I'd be happy to hear it!!

Basically here's my setup: Within the freeform:form I'm listing channel entries to populate the inputs

<input id="product_{count}" type="hidden" name="product[]" value="{sku}/" />
<input id="product_{count}" type="hidden" name="product[]" value="{title}/" />
<input id="product_{count}" type="hidden" name="product[]" value="{price}/" />
<input id="product_{count}" type="number" name="product[]" value="" />
<input id="product_{count}" type="hidden" name="product[]" value="," />

As stated, I don't know that this is the best approach, but it's the best I could figure out for now.

When a member views the page all they see is the input for the quantity, which is the line <input id="product_{count}" type="number" name="product[]" value="" />

When the form is submitted the product array comes in looking like:

[0] => 1011/
[1] => Product A/
[2] => 9.95/
[3] => 50
[4] => ,
[5] => 1011/
[6] => Product B/
[7] => 24.95/
[8] =>
[9] => ,
[10] => 1011/
[11] => Product C/
[12] => 11.95/
[13] => 12
[14] => ,

As you can see, element 8 is empty, this means that products was not ordered. So I need a way to skip that one.

So I've copied the text field type as a base to start off of from the Freeform pre-installed FieldTypes.

In the pre_process() method here is what I have created:

public function pre_process($data)
{
    if(is_array($data)){
        $data_string = implode($data);
        // print_r($data_string);
        // First get all the products into single lines we can work with
        $process_product = explode(",", $data_string);
        // String to hold our return value
        $return_str = "";
        // Loop through and process the extracted strings
        foreach($process_product as $value) {
            // Testing
            //echo($value . "<br/>");
            try{
                // Split the string by the "/" delimiter
                $explode = explode("/", $value);
                // Count should always be 4, even if no QTY entered, it will contain " "
                if(count($explode) == 4){
                    list($sku, $descr, $price, $qty) = explode("/", $value);
                    // Checking if there really is a QTY
                    if (trim($qty) !== "") {
                        // echo(" SKU: " . $sku . " Description: " . $descr . " Price: $" . $price . " Qty: " . $qty . "<br/>");
                        $ordered_product = (" SKU: " . $sku . "<br>" . " Description: " . $descr . "<br>" . " Price: $" . $price . "<br>" . " Qty: " . $qty . "<br>");
                        //echo($ordered_product);
                        $return_str .= $ordered_product . "<br>";
                    }
                }
            }
            catch (Exception $e){
                log_message('error', $e->getMessage()); 
                return;
            } // end try/catch
        }// end for

        // Final check to see if return_str is what we expect
        //echo($return_str);
        return $return_str;
    }

    return $data;
}

Basically I'm imploding the returned array so I can then delimit the string as needed. The string will now be in the format:

"1011/Product A/9.95/50,1011/Product B/24.95/,1011/Product C/11.95/12,"

This is working for both the front-end within the {exp:freeform:entries} tag pair, and also within the control panel. I get what I would expect. Basically it looks like this in the CP and on the front-end of the website:

SKU: 1011
Description: Product A
Price: $ 9.95
Qty: 50

But notifications are still receiving the original array in its entirety? This is my problem. I don't understand where the notifications are pulling the data from, and which function to use to process that data so I only get the data I need.

2 Answers 2

0

You can create custom notification templates from the Notifications section in the Freeform module in the CP, and assign this notification template to your form, either from the CP in the Forms section, or through parameters in your template.

In the CP when editing/creating a notification template, the notification email body can accept EE tags and variables, including embeds. You could use your PHP logic above and put this in a template, followed by loading the template in the notification body as an embed. Possibly, you could instead put this PHP logic directly in the notification body, although there is no setting for a PHP input/output setting there.

1
  • What a great idea! I didn't think of that. So would the variable passed to the embeds be an array still? When outputting straight in the notification template it just spits out the entire array but guessing it does some form of processing first (print_r($array)?)
    – shparkison
    May 15, 2014 at 14:53
0

In response to the reponse from Solspace, here's what I came up with:

{!--
    Basic usage:
    {embed="includes/process_notification" data="{myData}"}
    {embed:data} is now the data we're working with
--}

<?php

function processOutput($data)
{
    // First get all the products into single lines we can work with
    $process_product = explode(",", $data);
    // String to hold our return value
    $return_str = "";
    // Loop through and process the extracted strings
    foreach($process_product as $product) {
        try{
            // Split the string by the "/" delimiter
            $explode = explode("/", $product);
            // Count should always be 4, even if no QTY entered, it will contain " "
            if(count($explode) == 4){
                list($sku, $descr, $price, $qty) = explode("/", $product);
                // Checking if there really is a QTY
                if (trim($qty) !== "") {
                    // echo(" SKU: " . $sku . " Description: " . $descr . " Price: $" . $price . " Qty: " . $qty . "<br/>");
                    $ordered_product = ("<tr><td>" . $sku . "</td>" . "<td>" . $descr . "</td>" . "<td>(size)</td>" . "<td>" . $qty . "</td>" . "<td>" . $price . "</td></tr>");
                    //echo($ordered_product);
                    $return_str .= $ordered_product . "<br>";
                }
            }
        }
        catch (Exception $e){
            log_message('error', $e->getMessage()); 
            return;
        } // end try/catch
    }// end for

    return $return_str;

} // end output

$string = strip_tags("{embed:data}");
echo processOutput($string);

?>

The problem now is that nothing is output at all?? If I simply do a echo("{embed:data}"); I get the same thing as if I didn't use the embed at all, which is what I would expect. After testing the code on a string just like the one passed in as {embed:data} I get the output I'm after.

However, the code used as seen above returns nothing? I don't understand why it works on a raw string but not on "{embed:data}" ? I have php enabled on the template, and parse order is output.

EDIT: Problem was string passed in was html encoded (littered with <br> tags, so I needed to strip_tags first. Updated code shown above.

1
  • So I figured out the problem. The data passed to the template was html encoded, as soon as I strip_tags() it worked as expected!
    – shparkison
    May 15, 2014 at 19:20

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.