zaus / forms-3rdparty-xpost

Converts external submission from [Forms: 3rdparty Integration](http://wordpress.org/plugins/forms-3rdparty-integration/) plugin to XML post; optionally can add custom headers (to allow SOAP submissions).
4 stars 2 forks source link

Attribute Nesting Not Working As described #11

Closed rwilsond closed 8 years ago

rwilsond commented 9 years ago

I am looking to submit the following:

"Phone": [
                  {
                    "@attributes": {
                      "PhoneType": "personal"
                    },
                    "PhoneNumber": "999-999-9999"
                  },
                  {
                    "@attributes": {
                      "PhoneType": "cell"
                    },
                    "PhoneNumber": "777-777-7777"
                  },
                  {
                    "@attributes": {
                      "PhoneType": "office"
                    },
                    "PhoneNumber": "111-111-1111"
                  }
                ]

But when I actually do it I get:

"Phone":{
                        "@attributes":"personal, cell, office",
                        "PhoneNumber":"999-999-9999, 777-777-7777, 111-111-1111"
                     },

(The above resulted when using the default ", " separator.)

I then tried the following as well (without the quotes): "[]", "[] ", "[#] ", and "[#]" and none worked. Sometimes it would just add [] as if it were the comma, most of the time it just returned nothing in the post body (not valid JSON.)

In my case, I really only need to submit a phone number for Personal, and I can leave cell and office blank, but in the example above I added phone numbers to make it easier to follow.

Either way works (with blank cell and office numbers, or filler cell and office numbers).

I feel like I am overlooking something obvious, but I'm having a tough time figuring this out.

Any help would be appreciated IMMENSELY!

I'm running WP 4.1.1 Gravity Forms 1.9.6 Forms 3rd Party 1.6.4.1 Forms-3rdparty Xml Post 1.0

zaus commented 9 years ago

Sorry I didn't get to you sooner -- what mapping are you using?

zaus commented 9 years ago

Correction -- can you post the entire debug email (mapping + submission)

zaus commented 9 years ago

I tried guessing what could be coming across, not sure how you would set up a mapping to get what you want though -- http://sandbox.onlinephpfunctions.com/code/ca567488dae392bf881d297b6cc0bc7016e2bbd3

// not even sure how it'd come across...?
$result = nest(array(
    'Phone/0/@attributes/PhoneType' => 'personal',
    'Phone/0/PhoneNumber' => '999-999-9999',

    'Phone/1/@attributes/PhoneType' => 'work',
    'Phone/1/PhoneNumber' => '123-456-7899',

    'Phone/2/@attributes/PhoneType' => 'cell',
    'Phone/2/PhoneNumber' => '222-222-2222',
));

// this is probably how it's being provided, due to multi-value handling https://github.com/zaus/forms-3rdparty-integration/blob/master/forms-3rdparty-integration.php#L447
$result = nest(array(
    'Phone/@attributes/PhoneType' => array('personal', 'work', 'cell'),
    'Phone/PhoneNumber' => array('999-999-9999', '123-456-7899',
'222-222-2222'),
));
zaus commented 9 years ago

Interesting, numeric indices aren't supported very well... http://sandbox.onlinephpfunctions.com/code/8cfdbcf5419a5b23cef6417ad20a7252546c34d3

$result = nest(array(
    'Phone/a/@attributes/PhoneType' => 'personal',
    'Phone/a/PhoneNumber' => '999-999-9999',

    'Phone/b/@attributes/PhoneType' => 'work',
    'Phone/b/PhoneNumber' => '123-456-7899',

    'Phone/c/@attributes/PhoneType' => 'cell',
    'Phone/c/PhoneNumber' => '222-222-2222',
));
zaus commented 9 years ago

Aha - http://sandbox.onlinephpfunctions.com/code/4e788f1c8a7c545870caf834cbc08108a76d4f5a

So array_merge_recursive (used here) copies numeric indexes rather than overwriting them. A custom recursive merge will support them, but then the problem becomes how would you set up a mapping so that multiple responses don't essentially put the index at the end of the key mapping, but rather somewhere "inside", which is actually something for the 'Forms 3rdparty' plugin instead.

// http://php.net/manual/en/function.array-merge-recursive.php#82976
function array_merge_rec_i($arr,$ins) {
    # Loop through all Elements in $ins:
    if (is_array($arr) && is_array($ins)) foreach ($ins as $k => $v) {
        # Key exists in $arr and both Elemente are Arrays: Merge recursively.
        if (isset($arr[$k]) && is_array($v) && is_array($arr[$k])) $arr[$k] = array_merge_rec_i($arr[$k],$v);
            # Place more Conditions here (see below)
            # ...
            # Otherwise replace Element in $arr with Element in $ins:
        else $arr[$k] = $v;
    }
    # Return merged Arrays:
    return($arr);
}
zaus commented 9 years ago

And here's the trick -- need a new "separator style" [%] which will let us put the index as a placeholder in the mapped field, like:

$submission = array(
    'Phone/%i/@attributes/PhoneType' => array('personal', 'work', 'cell'),
    'Phone/%i/PhoneNumber' => array('999-999-9999', '123-456-7899',
'222-222-2222'),
);
function placeholder_separator($post) {
    $new = array(); // add results to new so we don't pollute the enumerator
    // find the arrays and reformat keys with index
    foreach($post as $f => $v) {
        if(is_array($v)) {
            // for each item in the submission array,
            // get its numerical index and replace the
            // placeholder in the destination field

            foreach($v as $i => $p) {
                $k = str_replace('%i', $i, $f);
                $new[$k] = $p;
            }

            unset($post[$f]); // now remove original, since we need to reattach under a different key
        }
    }
    return array_merge($post, $new);
}

see http://sandbox.onlinephpfunctions.com/code/5c2a626f6e5590281412863c7c3b14b143d935a7

rwilsond commented 9 years ago

Hey, sorry I wasn't online last night to respond.

So you're saying if I add the function placeholder_separator to my website it should work?

(I am assuming I would add it to my functions.php in Wordpress?)

zaus commented 9 years ago

Sorry for the late response -- you'd actually need to modify the Forms 3rdparty Integration plugin and add the case statement here to call the function I wrote above. It'd be a good addition, as I linked the enhancement issue (pull request anyone?)

rwilsond commented 9 years ago

Hi Zaus,

No worries!

Do you have an example showing how you added the case statement? I am having trouble applying your solution.

Thanks in advance, I'd be very grateful.

zaus commented 8 years ago

Assuming resolved due to 'native support' for this feature per referenced commit.