Last active
May 28, 2020 13:09
-
-
Save danielpost/9b989abf281e3333351e7ab1332572e8 to your computer and use it in GitHub Desktop.
WordPress API Importer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* This class is an example of how to reliably fetch items from an external API | |
* using background processing. Make sure Action Scheduler is installed before | |
* instantiating this class. | |
* | |
* @link https://actionscheduler.org/ | |
*/ | |
class Importer { | |
const API_URL = 'https://api.openbrewerydb.org/breweries'; | |
const ITEMS_PER_FETCH = 10; | |
const FETCH_ACTION = 'posty_fetch_breweries'; | |
const FETCH_SCHEDULE = '0 */6 * * *'; | |
/** | |
* @var int | |
*/ | |
public $page; | |
/** | |
* @var array | |
*/ | |
public $items = []; | |
/** | |
* @var bool | |
*/ | |
public $last_fetch = false; | |
public function setup() { | |
add_action(static::FETCH_ACTION, [$this, 'import']); | |
add_action('init', [$this, 'import_new_breweries']); | |
} | |
/** | |
* Get a list of items from the Open Brewery DB. | |
*/ | |
public function fetch() { | |
$response = wp_remote_get(static::API_URL, [ | |
'body' => [ | |
'per_page' => static::ITEMS_PER_FETCH, | |
'page' => $this->page | |
] | |
]); | |
if (wp_remote_retrieve_response_code($response) !== 200) { | |
// This means somewhere there was an issue with fetching. Perhaps | |
// the API timed out or the authentication was incorrect. Use this | |
// to gracefully handle failures. For this example, we simply write | |
// the error message to the log and stop the fetching process. | |
error_log(wp_remote_retrieve_response_message($response)); | |
$this->last_fetch = true; | |
return; | |
}; | |
$this->items = json_decode(wp_remote_retrieve_body($response)); | |
$this->process_items(); | |
} | |
/** | |
* Do something with each fetched item. | |
*/ | |
public function process_items() { | |
// If less items than requested are returned, we assume it was the last | |
// page and stop subsequent fetches. | |
if (count($this->items) < static::ITEMS_PER_FETCH) { | |
$this->last_fetch = true; | |
} | |
foreach ($this->items as $item) { | |
// Do something with an individual fetched item. For example, you | |
// could create a new custom post type entry for each item. It's | |
// also possible to stop the fetching process here, for example if | |
// the entry for this item already exists. | |
if (get_page_by_title($item->name)) { | |
$this->last_fetch = true; | |
continue; | |
} | |
// Process the item here... | |
} | |
} | |
/** | |
* Run the importer. | |
* | |
* @param int $page | |
*/ | |
public function import($page = 1) { | |
$this->page = $page; | |
$this->fetch(); | |
if (!$this->last_fetch) { | |
as_enqueue_async_action(static::FETCH_ACTION, [$this->page + 1]); | |
} else { | |
// Import finished. You could use this space to update an option or | |
// something else you'd like to do after finishing the import. | |
} | |
} | |
/** | |
* Run the importer according to the CRON schedule. | |
*/ | |
public function import_new_breweries() { | |
if (as_next_scheduled_action(static::FETCH_ACTION) === false) { | |
as_schedule_cron_action(time(), static::FETCH_SCHEDULE, static::FETCH_ACTION); | |
} | |
} | |
} | |
$importer = new Importer; | |
$importer->setup(); | |
// It's important to only kick off the initial import once, for instance | |
// when updating the API key settings. For this example however, we run it | |
// on every page load. | |
add_action('init', function () { | |
as_enqueue_async_action(Importer::FETCH_ACTION); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment