0

My question is how can I successfully crawl all levels of this serialized data and write each leaf level to separate strings in a file, where each line contains the array "key path" and the value. Basically, I need each value wrapped in a i18n function for translation purposes.

I have some serialized data in a mySQL database, here's a sample of a problematic value:

stdClass Object
(
 {...}
 [fields] => Array
    (
        [0] => stdClass Object
            (
            {...}
            [choices] => Array
                    (
                        [0] => stdClass Object
                            (
                                [text] => My string
                                [value] => 7
                                [isSelected] => 
                                [price] => 
                            )
     ) {...}

The expected result is each leaf value written to a PHP file with it's key hierearchy like this, so I can then reconvert it to an array:

$form['fields'][0]['choices'][0]['text'] = __( "My string", "tjxgallery" );

And here is my code that attempts to do that

$iterator = new RecursiveIteratorIterator( new RecursiveArrayIterator( $form_fields ) );

$strings_to_translate = array(
    '<?php' . PHP_EOL
);

foreach ( $iterator as $key => $value ) {

    // Fields to skip, as they don't contain any translatable strings
    $unwanted_fields = array(
        'inputName',
        'type',
        'size',
        'inputType',
        'descriptionPlacement',
        'postCustomFieldName',
        'allowedExtensions',
        'actionType',
        'operator',
        'logicType',
        'conditionalLogic',
    );

    // Only proceed if array item is a string and it's not empty and it's not a number and it's not in the ignored fields
    if ( ! in_array( $key, $unwanted_fields ) && ( is_string( $value ) && ( 0 < strlen( $value ) ) &&  ! is_numeric( $value ) ) ) {

        // Iterate through the sub arrays
        for ( $i = $iterator->getDepth() - 1; $i >= 0; $i -- ) {

            $path = '';

            // get the parent key of current item
            $subkey = $iterator->getSubIterator( $i )->key();

            // Build a string with the full key path - e.g. [0]['choices'][0]['text']
            if ( is_numeric( $subkey ) ) {

                if ( empty( $path ) ) {

                    $path = '[' . $subkey . '][\'' . $key;

                } else {

                    $path = '[' . $subkey . ']' . $key;

                }

            } else {

                if ( empty( $path ) ) {

                    $path = '[\'' . $subkey . '\'][\'' . $key;

                } else {

                    $path = '[\'' . $subkey . '\']' . $key;

                }

            }

        }

        // Build an array of translation ready strings e.g. $form['fields'][0]['text'] = __( "Give Up Clothes For Good – Cancer Research UK", "tjxgallery" );
        $strings_to_translate[] = '$form[\'fields\']' . $path . '\'] = __( "' . preg_replace( "/\n/", '', $value ) . '", "tjxgallery" );' . PHP_EOL;

    }

The result I get now is this: $form['fields'][0]['text'] = __( "My string", "tjxgallery" );

So , it's missing the ['choices'][0] part.

Any help appreciated

thanks for your time

1
  • Are you looking to create $path each time or to append text to it? Commented Aug 26, 2014 at 15:08

2 Answers 2

1

I added echo statements all over the place in your code to track down where the problem was occurring. I think there were two issues: one, $path is in an inner loop and keeps getting reset, and two, $path was being replaced each time, rather than having text appended to it.

This is what worked for me:

foreach ( $iterator as $key => $value ) {

    // Fields to skip, as they don't contain any translatable strings
    $unwanted_fields = array(
        ...
    );
    // Only proceed if array item is a string and it's not empty
    // and it's not a number and it's not in the ignored fields
    if ( ! in_array( $key, $unwanted_fields ) && ( is_string( $value ) && ( 0 < strlen( $value ) ) &&  ! is_numeric( $value ) ) ) {

        // start a new path from $key here.
        $path = '';

        // Iterate through the sub arrays
        for ( $i = $iterator->getDepth() - 1; $i >= 0; $i -- ) {

            // get the parent key of current item
            $subkey = $iterator->getSubIterator( $i )->key();
            // Build a string with the full key path - e.g. [0]['choices'][0]['text']
            $path .= '[\'' . $subkey . '\']';
        }
        // OK, we've constructed the path. Add $key to the end.
        $path .= '[\'' . $key . '\']';

        // Build an array of translation ready strings e.g. $form['fields'][0]['text'] = __( "Give Up Clothes For Good – Cancer Research UK", "tjxgallery" );
        echo '$form[\'fields\']' . $path . ' = __( "' . preg_replace( "/\n/", '', $value ) . '", "tjxgallery" );' . "\n";

    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

The accepted reply gets me most of the way, but I still needed to check if a key is numeric because it has to be [0] not ['0']

Also, still need to figure out why the keys are not in the correct order:

$form['fields'][0]['choices'][0]['text'] = __( "String 1", "tjxgallery" );
$form['fields'][1]['choices'][0]['text'] = __( "String 2", "tjxgallery" );
$form['fields'][2]['choices'][0]['text'] = __( "String 3", "tjxgallery" );
$form['fields'][3]['choices'][0]['text'] = __( "String 4", "tjxgallery" );

should be ( note the numeric keys are swapped:

$form['fields'][0]['choices'][0]['text'] = __( "String 1", "tjxgallery" );
$form['fields'][0]['choices'][1]['text'] = __( "String 2", "tjxgallery" );
$form['fields'][0]['choices'][2]['text'] = __( "String 3", "tjxgallery" );
$form['fields'][0]['choices'][3]['text'] = __( "String 4", "tjxgallery" );

Here is what needs to be changed:

if ( is_numeric( $subkey ) ) {
    $path = '[' . $subkey . ']' . $path;
} else {
    $path =  '[\'' . $subkey . '\']' . $path;
}

So adding the keys in reverse.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.