0

I'm trying to save the field values of a PHP form to a json file. I've tried a few solutions from this site which helped but I ran into an issue where it's not grabbing the field values and not returning any errors (I checked the logs). I am new to PHP so I'm probably making a noob mistake.

I am trying to use the solution posted here https://stackoverflow.com/a/17923066/1747477

Also, I need to replace the nested array with index "bundled_plugins" that is already present in the JSON file and not append it to the existing nested array. I'm using array_push but I know I need to use array_replace but I don't know how to target a specific index. If someone can point me in the right direction?

FORM

<form action="<?php $_SERVER["PHP_SELF"]; ?>" method="post" role="form">

<div class="form-group">

    <label for="plugin1">Plugin 1</label>
    <input type="url" class="form-control" title="Enter the plugin's download URL" name="plugin[1][download]" id="plugin1_download" placeholder="https://downloads.wordpress.org/plugin/plugin-name.latest-stable.zip" value="<?php echo $settings->bundled_plugin_1_download; ?>" pattern="https://.*" size="100" required>

</div>

<div class="form-group">

    <input type="text" class="form-control" title="Enter the plugin's basename" name="plugin[1][file]" id="plugin1_file" placeholder="directory-name/primary.php" value="<?php echo $settings->bundled_plugin_1_file; ?>" size="100" required>

</div>

<div class="form-group">

    <label for="plugin2">Plugin 2</label>
    <input type="url" class="form-control" title="Enter the plugin's download URL" name="plugin[2][download]" id="plugin2_download" placeholder="https://downloads.wordpress.org/plugin/plugin-name.latest-stable.zip" value="<?php echo $settings->bundled_plugin_2_download; ?>" pattern="https://.*" size="100">

</div>

<div class="form-group">

    <input type="text" class="form-control" title="Enter the plugin's basename" name="plugin[2][file]" id="plugin2_file" placeholder="directory-name/primary.php" value="<?php echo $settings->bundled_plugin_2_file; ?>" size="100">

</div>

<div class="form-group">

    <label for="plugin3">Plugin 3</label>
    <input type="url" class="form-control" title="Enter the plugin's download URL" name="plugin[3][download]" id="plugin3_download" placeholder="https://downloads.wordpress.org/plugin/plugin-name.latest-stable.zip" value="<?php echo $settings->bundled_plugin_3_download; ?>" pattern="https://.*" size="100">

</div>

<div class="form-group">

    <input type="text" class="form-control" title="Enter the plugin's basename" name="plugin[3][file]" id="plugin3_file" placeholder="directory-name/primary.php" value="<?php echo $settings->bundled_plugin_3_file; ?>" size="100">

</div>

<div class="form-group">

    <label for="plugin4">Plugin 4</label>
    <input type="url" class="form-control" title="Enter the plugin's download URL" name="plugin[4][download]" id="plugin4_download" placeholder="https://downloads.wordpress.org/plugin/plugin-name.latest-stable.zip" value="<?php echo $settings->bundled_plugin_4_download; ?>" pattern="https://.*" size="100">

</div>

<div class="form-group">

    <input type="text" class="form-control" title="Enter the plugin's basename" name="plugin[4][file]" id="plugin4_file" placeholder="directory-name/primary.php" value="<?php echo $settings->bundled_plugin_4_file; ?>" size="100">

</div>

<div class="form-group">

    <label for="plugin5">Plugin 5</label>
    <input type="url" class="form-control" title="Enter the plugin's download URL" name="plugin[5][download]" id="plugin5_download" placeholder="https://downloads.wordpress.org/plugin/plugin-name.latest-stable.zip" value="<?php echo $settings->bundled_plugin_5_download; ?>" pattern="https://.*" size="100">

</div>

<div class="form-group">

    <input type="text" class="form-control" title="Enter the plugin's basename" name="plugin[5][file]" id="plugin5_file" placeholder="directory-name/primary.php" value="<?php echo $settings->bundled_plugin_5_file; ?>" size="100">

</div>

<div class="form-group">

    <button id="bundle_plugins" type="submit" name="bundle_plugins" class="btn btn-md btn-success">Save</button>

</div>

PHP FUNCTION

public function bundle_plugins() {

    $settings = "settings.json";
    $arr_data = array();

    $plugins = array();
    foreach($_POST['plugin'] as $key => $val) {
        $plugins[] = array(
            'download' => $_POST['plugin'][$key],
            'file' => $_POST['plugin'][$key]
        );
    }

    // Get data from existing json file
    $jsondata = file_get_contents($settings);

    // Converts json data into array
    $arr_data = json_decode($jsondata, true);

    // Push user data to array
    array_push($arr_data, $plugins);

    // Convert updated array to JSON
    $jsondata = json_encode($arr_data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

    //write json data into data.json file
    if(file_put_contents($settings, $jsondata)) {
        echo "<div class='alert alert-success' role='alert'>Plugins successfully bundled!</div>";
    }
    else {
        echo "<div class='alert alert-danger' role='alert'><strong>ERROR</strong> Please check you have entered the plugin download URL and basename correctly and try again.</div>";
    }

}

JSON

{
    "bundled_plugins": [
        {
            "download": "https://downloads.wordpress.org/plugin/classic-editor.latest-stable.zip",
            "file": "classic-editor/classic-editor.php"
        },
        {
            "download": "https://downloads.wordpress.org/plugin/defender-security.latest-stable.zip",
            "file": "defender-security/wp-defender.php"
        }
    ]
}

EDIT:

{
    "bundled_plugins": [
        {
            "download": "https://downloads.wordpress.org/plugin/classic-editor.latest-stable.zip",
            "file": "classic-editor/classic-editor.php"
        },
        [
            {
                "download": "https://downloads.wordpress.org/plugin/classic-editor.latest-stable.zip",
                "file": "classic-editor/classic-editor.php"
            },
            {
                "download": "",
                "file": ""
            },
            {
                "download": "",
                "file": ""
            },
            {
                "download": "",
                "file": ""
            },
            {
                "download": "",
                "file": ""
            }
        ]
    ]
}

EDIT 2:

This is the json file if I switch to array_replace. The bundled_plugins index is removed.

[
    {
        "download": "https://downloads.wordpress.org/plugin/classic-editor.latest-stable.zip",
        "file": "classic-editor/classic-editor.php"
    },
    {
        "download": "https://downloads.wordpress.org/plugin/test.latest-stable.zip",
        "file": "classic-editor/test.php"
    }
]

SOLUTION

public function bundle_plugins() {

        $settings = "settings.json";
        $arr_data = array();
        
        $plugins = array();
        foreach($_POST['plugin'] as $key => $val) {
            if( !empty($_POST['plugin'][$key]['download']) && !empty($_POST['plugin'][$key]['file'])) {
                $plugins['bundled_plugins'][] = $_POST['plugin'][$key];
            }
        }

        // Get data from existing json file
        $json = file_get_contents($settings);

        // Converts json data into array
        $arr_data = json_decode($json, true);

        // Push user data to array
        $arr_data = array_replace($arr_data, $plugins);

        // Convert updated array to JSON
        $json = json_encode($arr_data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

        //write json data into data.json file
        if(file_put_contents($settings, $json)) {
            echo "<div class='alert alert-success' role='alert'>Plugins successfully bundled!</div>";
        }
        else {
            echo "<div class='alert alert-danger' role='alert'><strong>ERROR</strong> Please check you have entered the plugin download URL and basename correctly and try again.</div>";
        }

    }
8
  • 1
    1. is there really a input type="url" type? 2. You need $_POST['plugin'][$key]['file'] and $_POST['plugin'][$key]['download'] Commented Aug 24, 2020 at 15:24
  • @AbraCadaver apparently so w3schools.com/tags/att_input_type_url.asp. Will try your suggestion. Commented Aug 24, 2020 at 15:32
  • Ok, never used it before. Commented Aug 24, 2020 at 15:33
  • @AbraCadaver Tried it but still getting same results. No change and no errors... something to do with this $_POST['plugin'][$key]['file'] most likely the issue. Not grabbing the input values. Commented Aug 24, 2020 at 15:41
  • Do you ever call bundle_plugins()? What echo do you get at the end of it? Commented Aug 24, 2020 at 15:43

1 Answer 1

1

First you are ignoring the POST plugin keys download and file. Second just merge the new array into the existing one:

foreach($_POST['plugin'] as $key => $val) {
    $plugins[] = array(
        'download' => $_POST['plugin'][$key]['download'],
        'file' => $_POST['plugin'][$key]['file']
    );
}

// Get data from existing json file
$jsondata = file_get_contents($settings);

// Converts json data into array
$arr_data = json_decode($jsondata, true);

$arr_data = array_merge($arr_data['bundled_plugins'], $plugins);

The loop could be simpler since the keys are already in the POST:

foreach($_POST['plugin'] as $key => $val) {
    $plugins[] = $_POST['plugin'][$key];
}

Or maybe just if you don't need to do anything else: $plugins = $_POST['plugin'];

But, you probably want to check the the POST values are !empty() before adding to the $plugins array and also check $plugins array before merging so you don't get empties.

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

2 Comments

Your code suggestions work nicely. I switched to array_replace which works but strips out the bundled_plugins index. See my EDIT 2 in the question.
Finally figured it out after some trial and error. Posted the final solution. Thanks for all your help!

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.