views:

41

answers:

2

I'm using a wordpress plugin for advanced form design/logic/processing, and one of it's (biggest) downsides is the awkward way it provides form data. Data is given in an array with two or three items for each field.

if it's a hidden field:

  1. $$$n => id - where n is the field's order in the form, and NAME is the name/id.
  2. id => value - where id is the name/id and value is the value.

If it's a visible field:

  1. $$$n => LABEL - where n is the field's order in the form, and LABEL is the human-readable label.
  2. $$$id => LABEL - where id is the name/id of the field
  3. LABEL => value - where value is what I actually want.

I'm trying to write a function that will consume this horrid array and return a simpler one with a single id => value pair for each field.

For example, it will take this (order of fields can't be guaranteed):

array(
    '$$$1' => 'command',
    'command' => 'signup',
    '$$$2' => 'First Name',
    '$$$firstname' => 'First Name',
    'First Name' => 'John',
    '$$$3' => 'Email Address',
    '$$$email' => 'Email Address',
    'Email Address' => '[email protected]'
);

And return:

array(
    'command' => 'signup',
    'email' => '[email protected]',
    'firstname' => 'John'
);

This code works, but feels very awkward. Can you help refine it? Thanks! (My strategy is to ignore everything but the $$$n fields since they're identical for all forms and there's no simple way to tell if a given field is hidden or not.)

function get_cforms_data($cformsdata) {
$data = array();
foreach ($cformsdata as $key => $value) {
    if (strpos($key, '$$$') === 0) {
        $newkey = substr($key, 3);
        if (is_numeric($newkey)) {
            $keys = array_keys($cformsdata, $value);
            if (count($keys) == 1) {
                // must be a hidden field - NAME only appears once
                $data[$value] = $cformsdata[$value];
            } else {
                // non-hidden field.  Isolate id.
                foreach($keys as $k) {
                    if ($k == $key) {
                        // $$$n - ignore it
                        continue;
                    } else {
                        // $$$id
                        $k = substr($k, 3);
                        $data[$k] = $cformsdata[$value];
                    }
                }
            }
        }
    }
}
return $data;
}
+2  A: 

Here's a working version:

$i=0;
$result = array();

while (array_key_exists('$$$' . ++$i, $arr)) {
    $key = $arr['$$$' . $i];
    $result[$key] = $arr[$key];
}

It will print:

Array
(
    [command] => signup
    [First Name] => John
    [Email Address] => [email protected]
)

Here's another version. It is much uglier but does exactly what you want (as I interpreted it)

function get_cforms_data($cformsdata) {
    $i=0;
    $result = array();
    $flipped = array_flip($arr);

    while (array_key_exists('$$$' . ++$i, $arr)) {
        $key = $arr['$$$' . $i];

        $realKey = (!preg_match('~^\${3}\d+$~', $flipped[$key])) ? 
                    substr($flipped[$key], 3) : $key;

        $result[$realKey] = $arr[$key];
    } 
    return $result;   
}

Returns:

Array
(
    [command] => signup
    [firstname] => John
    [email] => [email protected]
)

See it working: http://ideone.com/5mkbx

NullUserException
+1 Very efficient.
Tomalak
Thanks, but pls double-check the question. I want the output keys to be the **id** values, not the human-readable labels.
Benj
@Benj see my 2nd algorithm
NullUserException
Nice. Accepting it for elegance, although in the end my preferred solution is hacking the plugin to make it just build a functional array in the first place!
Benj
A: 

Here's what I'd probably do, though I don't think it's that much cleaner than yours or NullUserException's:

function get_cforms_data($cforms_data) {
    $ret = array();
    $label_to_id = array();
    $label_or_id_to_value = array();
    foreach ($cforms_data as $key => $value) {
        if (substr($key, 0, 3) === "$$$") {
            if (!is_numeric($id = substr($key, 3))) {
                $label_to_id[$value] = $id;
            }
        } else {
            $label_or_id_to_value[$key] = $value;
        }
    }
    foreach ($label_or_id_to_value as $key => $value) {
        $ret[isset($label_to_id[$key]) ? $label_to_id[$key] : $key] = $value;
    }
    return $ret;
}
bcat