DEV Community

Matteo De Filippis
Matteo De Filippis

Posted on

How to import CSV data into WordPress Custom Fields

As a developer in a communications house, I tend to use WordPress a lot because it is a well-known and client-friendly platform.
One of the requests I receive most often from clients is to be able to use spreadsheets to enter data into the site.

Usually, this data has to be inserted within custom fields that allow us to create beautiful custom UI experiences without sacrificing the ease of use of WordPress.

There are already many solutions on the market for importing CSV files within custom fields, but they are all expensive and not open-source.

For this reason, I created a simple plugin that allows you to create new custom fields from the file's columns and then create pages (or other custom post types) by filling the fields with the contents of those columns.

It should be noted that the plugin is still in the alpha stage so it may contain bugs and glitches. Prior knowledge of custom fields, custom post types, and similar concepts is preferable to understand how it works.

Any pull requests or issues in the repo are appreciated.


Prerequisites

The plugin works in a simple way. All data parsing and cleaning is done client-side, while database entry is done server-side.

For the plugin to work, it is necessary to have the Advanced Custom Fields plugin installed. Also, the only supported custom field types are text, image, oEmbed, and link.

There are also some prerequisites regarding file formatting for the plugin to work correctly. Specifically:

  • The first row must contain the field names or at least an indication of the contents of each column. It must not include the data to be imported in any case.
  • Every other row must contain the data to be imported. In particular, each row must correspond to the contents of a page.
  • The first column must contain the title of the page.
  • The image fields must contain the URL of the image. The URL must point directly to the image file, not the page where the image is displayed (Google Drive preview, Dropbox, and the like).

N.B: When the image link does not provide the image extension, the plugin sets it to .jpg by default.


How does it work

  1. The loaded CSV file is parsed into a JSON structure. The latter is previewed to verify that the data has been correctly loaded.
  2. Then, you can select which content type to import the data into (pages, posts, or any custom post type) and enter the name of the custom fields group to be inserted into the database.
  3. A page is then shown where you can specify the label, name, and type for each field detected in the file. An autocomplete button is also available to fill all fields with the contents of the first line of the CSV file. The label for each field coincides with the contents of the relevant column, the name is created in snake case, and the type is automatically set as text.
  4. Once the fields have been created and entered into the database, you can decide whether to automatically publish the pages or save them as a draft.
  5. You can start the import of the pages

The code

The plugin is based on Devin Vinson's boilerplate and has a very simple structure.

The main files are contained in the admin folder. In particular, all client-side functions are contained in the admin/js/csv-to-acf-admin.js file and are sufficiently self-explanatory.

On the server side, two APIs take care of custom field creation and data import.

create-field-group.php

This API deals with the insertion of new custom fields into the database.

First, a check is made on the installation of Advanced Custom Fields and the presence of all the necessary parameters

// Check if ACF is installed
if (!class_exists("ACF")) {
    print_r("ACF is not installed");
    return;
};

// Check if all required parameters are present
if (empty($_POST['title']) || empty($_POST['fields']) || empty($_POST['location']) || empty($_POST['headers'])) {
    print_r("Missing parameters");
    return;
};
Enter fullscreen mode Exit fullscreen mode

Next, the custom field group is saved to the database using the acf_import_field_group($field_group) function (contained in the includes/acf-field-group-functions.php file in the ACF plugin folder).

The function takes in an array related to the custom fields group, built following the ACF documentation itself.

// Get parameters
$group_title = $_POST['title'];
$fields = $_POST['fields'];
$location = $_POST['location'];
$headers = $_POST['headers'];

// Create field group
$group = array(
    'key' => 'group_' . md5($group_title),
    'title' => $group_title,
    'fields' => $fields,
    'location' => array(
        array(
            array(
                'param' => 'post_type',
                'operator' => '==',
                'value' => $location,
            ),
        ),
    ),
);
$field_group = acf_import_field_group($group);
Enter fullscreen mode Exit fullscreen mode

Finally, the keys of the JSON object are modified with the new names related to the custom fields to facilitate subsequent import operations, and the result is returned to the caller as a string

// Create array with old and new field names, to be used by JS to update the JSON object with the new field names
$names = [];

foreach ($fields as $key => $field) {
    $temp = [];
    $temp['new_name'] = $field['name'];
    $temp['old_name'] = $headers[$key];
    array_push($names, $temp);
}

if ($field_group) {
    echo json_encode($names);
} else {
    print_r("Error creating field group");
}
Enter fullscreen mode Exit fullscreen mode

import-data.php

As for the data import, after the usual initial checks, we proceed to decode the JSON string sent from the csv-to-acf-admin.js file

// Get parameters
$data = $_POST['data'];
$publish = $_POST['publish'];
$post_type = $_POST['post_type'];

// Decode JSON string
$tmp = substr($data, 1, -1);
$tmp = preg_split('/(?<=\})(.*?)(?=\{)/', $tmp);
foreach ($tmp as $key => $value) {
    $value = html_entity_decode(stripslashes($value));
    $tmp[$key] = json_decode($value, true);
}
Enter fullscreen mode Exit fullscreen mode

Next, for each line, we proceed with the creation of a new page, using the wp_insert_post() function.

// Create posts
foreach ($tmp as $key => $row) {

    // Skip empty rows
    if ($row[array_key_first($row)] == '') {
        continue;
    }

    // Create post
    $post = array(
        'post_title' => $row[array_key_first($row)],
        'post_content' => '',
        'post_status' => $publish == "publish" ? 'publish' : 'draft',
        'post_type' => $post_type,
    );
    $post_id = wp_insert_post($post);


Enter fullscreen mode Exit fullscreen mode

Finally, the custom fields are filled in. In particular, if the field in question is a link, an array is created for the update_field() function to succeed.

Currently, the target attribute and link title are fixed values, but in a future release they may be editable


    // Add ACF fields
    if ($post_id) {
        foreach ($row as $field => $value) {

            // Skip empty fields
            if ($value == '') {
                continue;
            } elseif (acf_get_field($field)['type'] == 'link') {
                // Create link
                $site = array(
                    'title' => 'Link',
                    'url' => $value,
                    'target' => '',
                );
                update_field($field, $site, $post_id);
Enter fullscreen mode Exit fullscreen mode

If, on the other hand, the field in question is for an image, the file is first downloaded and uploaded to the WordPress media library. Only then its ID is used to update the contents of the field.


            } elseif (acf_get_field($field)['type'] == 'image') {

                // Sets upload directory and sets file type
                $uploaddir = wp_upload_dir();
                $uploadurl = $uploaddir['url'] . '/' . basename($value);
                $uploadfile = $uploaddir['path'] . '/' . basename($value);
                $wp_filetype = wp_check_filetype(basename(basename($value)), null);
                $filetype = $wp_filetype['type'];

                // Add .jpg extension if no extension is present
                if (pathinfo(basename($value), PATHINFO_EXTENSION) == "") {
                    $uploadfile .= ".jpg";
                    $uploadurl .= ".jpg";
                    $filetype = 'image/jpeg';
                };

                // Download image
                $image = file_get_contents($value);
                file_put_contents($uploadfile, $image);

                // Add image to media library
                $attachment = array(
                    'post_mime_type' => $filetype,
                    'post_title' => basename($value),
                    'post_content' => '',
                    'post_status' => 'inherit',
                    'guid' => $uploadurl,
                );
                $attach_id = wp_insert_attachment($attachment, $uploadfile);

                // Add image to ACF field
                if ($attach_id > 0 && !is_wp_error($attach_id)) {
                    update_field($field, $attach_id, $post_id);
                }
Enter fullscreen mode Exit fullscreen mode

Finally, if the field is a text or an oEmbed, the field is updated by directly entering the desired value.


            } else {
                // Add other fields
                update_field($field, $value, $post_id);
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Links

You can find the repo on GitHub: if you liked my work, give me a star or feel free to contribute with a PR or issue!

GitHub logo matteodf / csv-to-acf

Import CSV data into new pages creating proper ACF fields.

CSV to ACF Importer

Description

This plugin allows you to import CSV data into new pages creating proper ACF fields.

It takes the first row of the CSV file as the field names and the following rows as the data The plugin will create a new ACF group for each CSV file and will create a new page for each row of data.

Each ACF group will have a field for each column of the CSV file. The user can choose the field type for each field.

Currently supports text, image, link and oEmbed fields.

After the creation of the fields, the plugin will import the data into the new pages. The user can choose if the pages should be published or not.

Installation

  1. Upload csv-to-acf folder to the /wp-content/plugins/ directory
  2. Activate the plugin through the 'Plugins' menu in WordPress
  3. Go to the plugin settings page and upload your CSV…

Top comments (0)