Adding a WP-CLI Command to Your Plugin, Part 2

The previous article, I showed how to add a WP-CLI command to your plugin. In this tutorial I define the methods to read the CSV data files from standard input, and dump it to the screen.

The input data looks like this. First is the “cities” data:

FEATURE_ID|FEATURE_NAME|FEATURE_CLASS|CENSUS_CODE|CENSUS_CLASS_CODE|GSA_CODE|OPM_CODE|STATE_NUMERIC|STATE_ALPHA|COUNTY_SEQUENCE|COUNTY_NUMERIC|COUNTY_NAME|PRIMARY_LATITUDE|PRIMARY_LONGITUDE|DATE_CREATED|DATE_EDITED
22753|Colorado River Indian Reservation|Civil|0735R|D2|||04|AZ|1|012|La Paz|33.9317167|-114.3886436|06/27/1984|12/01/2016
22753|Colorado River Indian Reservation|Civil|0735R|D2|||06|CA|2|065|Riverside|33.9317167|-114.3886436|06/27/1984|12/01/2016

That’s pipe-separated text without quotes.

The second is the “zips” data:

"Zipcode","ZipCodeType","City","State","LocationType","Lat","Long","Location","Decommisioned","TaxReturnsFiled","EstimatedPopulation","TotalWages"
"90001","STANDARD","LOS ANGELES","CA","PRIMARY",33.97,-118.24,"NA-US-CA-LOS ANGELES","false",18561,36200,421709138
"90002","STANDARD","LOS ANGELES","CA","PRIMARY",33.94,-118.24,"NA-US-CA-LOS ANGELES","false",16133,30920,352278879
"90003","STANDARD","LOS ANGELES","CA","PRIMARY",33.96,-118.27,"NA-US-CA-LOS ANGELES","false",21982,41878,463744071

This looks more like the data produced by Excel.

Here’s the code to read these files.

<?php

namespace JK\DMPM;
use \WP_CLI;

WP_CLI::add_command('bizdir import', 'JK\DMPM\Import_Command');
class Import_Command {
    public function cities() {
        while ($fields = fgetcsv(STDIN, 1024, '|')) {
            print_r($fields);
        }
    }
    public function zips() {
        while ($fields = fgetcsv(STDIN, 1024)) {
            print_r($fields);
        }
    }
}

While I’m developing, I use this command to check my parsing:

head -3 ../SomeZipsFile.csv | wp bizdir import zips

If I wanted to run that over and over, this is less work:

watch 'head -3 ../SomeZipsFile.csv | wp bizdir import zips'

That runs the command every two seconds.

Then, I can pluck out the fields one by one with code like this:

    public function zips() {
        while ($fields = fgetcsv(STDIN, 1024)) {
            print_r($fields);
            $data = array();
            $data['zip'] = $fields[0];
            $data['city'] = $fields[2];
            $data['lat'] = $fields[5];
            $data['lon'] = $fields[6];
            print_r($data);
        }
    }

Dumping the data with print_r() made it really easy to see if I was picking the right columns. The first record showed whether my picks matched the headings, and the second and third showed the data.

Inserting Into the Database

This is the zips() function modified to insert the data into the table:

    public function zips() {
        global $wpdb;
        $tablename = $wpdb->prefix.'dmpm_zip';

        fgetcsv(STDIN, 1024); // skip the header line
        while ($fields = fgetcsv(STDIN, 1024)) {
            $data = array();
            $data['id'] = $fields[0];
            $data['city'] = $fields[2];
            $data['lat'] = $fields[5];
            $data['lon'] = $fields[6];
            $wpdb->insert($tablename, $data);
        }
    }

If you’re already coding WordPress plugins, that code should look familiar and comfortable. $wpdb has a nice method, insert() that inserts an array into the specified table.

We also wanted to get rid of our header row, so before we go into a loop, we do:

    fgetcsv(STDIN, 1024); // skip the header line

That’s pretty much it. I repeated the process to write the importer for cities.

WP-CLI Commands May Require Less Code

This command line importer used less code than a similar wp-admin feature to import spreadsheet data into a table. The fgetcsv() function replaced a lot of code. Here’s a fragment of the wp-admin feature that parsed data pasted from a LibreOffice spreadsheet:

function import_csv_to_table($csv) {
    global $wpdb;
    $rows = preg_split('/[\\n\\r]+/', ltrim(rtrim($csv)));
    foreach($rows as $row) {
        $cols = preg_split('/[,\\t]/', $row);
        for($i=0; $i<9; $i++) {
            if (isset($cols[$i])) { 
                $cols[$i] = stripslashes($cols[$i]); 
            } else { 
                $cols[$i]=''; 
            }
        }

That’s incomplete – but fgetcsv() function did the same work. The actual code was twice as long, or around 25 lines.

Additionally, to make a wp-admin page, you need to display the form, and handle the input, and display errors. I had around 40 lines of code to do that. So, we’re looking at a 10-15 lines of code for the WP-CLI version, versus over 60 lines of code for the wp-admin version.

So, clearly, for anything like importing data in bulk, adding a WP-CLI command is preferable to adding a feature in wp-admin.

In the next article, we’ll go over adding documentation to the command.

Next: Part 3

One thought on “Adding a WP-CLI Command to Your Plugin, Part 2”

Leave a Reply