Skip to content

Instantly share code, notes, and snippets.

@drewbaker
Last active September 6, 2023 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save drewbaker/80347e2596ce67331d5487f5e977f989 to your computer and use it in GitHub Desktop.
Save drewbaker/80347e2596ce67331d5487f5e977f989 to your computer and use it in GitHub Desktop.
A script that creates a Video CPT that gets synced to your Simian
<?php
/*
* This file contains code to create a Video CPT, and a "Download" button in the admin header.
* When clicking that download button, it creates a Video post with all the meta data saved as `simian_data`.
*
* Requires a site options field for `simian_api_key` that is the API key from Simian.
* Eg: This must work: get_field("simian_api_key", "option");
*
* Also need an option field for `simian_api_url` that is something like `https://clientNameHere.gosimian.com/api/simian/get_media`
*
* The download button works by going to the path `edit.php?post_type=videos&simian_refresh_media`
* Which will trigger a download of data from Simian.
*
* You can also manually go to `edit.php?post_type=videos&simian_api_test` to see a test of the API results.
*/
class Crawler
{
public static function getCurl()
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_REFERER, "http://google.pl");
curl_setopt(
$curl,
CURLOPT_USERAGENT,
"Mozilla/6.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"
);
curl_setopt(
$curl,
CURLOPT_COOKIEFILE,
dirname(__FILE__) . "/cookies.txt"
);
curl_setopt(
$curl,
CURLOPT_COOKIEJAR,
dirname(__FILE__) . "/cookies.txt"
);
curl_setopt($curl, CURLOPT_AUTOREFERER, true);
curl_setopt($curl, CURLOPT_VERBOSE, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
return $curl;
}
public static function getBetween($left, $right, $source, $offset = 1)
{
$step1 = explode($left, $source);
if (count($step1) < 2 + $offset - 1) {
return false;
}
$step2 = explode($right, $step1[1 + $offset - 1]);
if (isset($step2[0])) {
return trim(preg_replace("/\s\s+/", " ", $step2[0]));
}
return false;
}
}
/**
* Register Videos CPT, this is where Simian videos get saved to
*/
function simian_videos_cpt()
{
$labels = [
"name" => _x("Videos", "post type general name", "wordpress"),
"singular_name" => _x("Video", "post type singular name", "wordpress"),
"menu_name" => _x("Videos", "admin menu", "wordpress"),
"name_admin_bar" => _x("Video", "add new on admin bar", "wordpress"),
"add_new" => _x("Add Video", "bio", "wordpress"),
"add_new_item" => __("Add Video", "wordpress"),
"new_item" => __("New Video", "wordpress"),
"edit_item" => __("Edit", "wordpress"),
"view_item" => __("View", "wordpress"),
"all_items" => __("All Videos", "wordpress"),
];
$args = [
"labels" => $labels,
"description" => __("Description.", "wordpress"),
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_menu" => true,
"show_in_admin_bar" => false,
"query_var" => true,
"rewrite" => ["slug" => "videos", "with_front" => false],
"capability_type" => "post",
"has_archive" => true,
"hierarchical" => false,
'menu_icon' => 'dashicons-format-video',
"menu_position" => null,
"supports" => ["thumbnail", "title", "editor", "custom-fields"],
'show_in_graphql' => true,
'show_in_rest' => true,
'graphql_single_name' => 'VideoPost',
'graphql_plural_name' => 'VideoPosts',
];
register_post_type("videos", $args);
}
add_action("init", "simian_videos_cpt");
/**
* Function that can be used to test that the Simian API is working
*/
function simian_download_from_api()
{
if (isset($_GET["simian_api_test"])) {
$api_key = get_field("simian_api_key", "option");
$api_url = get_field("simian_api_url", "option");
$curl = Crawler::getCurl();
/*
API Call Information:URL: https://clientNameHere.gosimian.com/api/simian/get_reel
HTTP POST Parameters:
reel_id: 1
reel_type: web_reelss
* */
curl_setopt($curl, CURLOPT_URL, $api_url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, [
"auth_token" => $api_key,
"output_format" => "json",
]);
$response = curl_exec($curl);
$response = json_decode($response);
var_dump($response);
die();
}
if (isset($_GET["simian_refresh_media"])) {
$result = simian_refresh_media();
if ($result) {
add_action('admin_notices', 'husdson_admin_refresh_success');
} else {
add_action('admin_notices', 'husdson_admin_refresh_error');
}
}
}
add_action("init", "simian_download_from_api");
/**
* The message that is displayed on success of Simian data
*/
function husdson_admin_refresh_success()
{
?>
<div class="notice notice-success is-dismissible">
<p>Simian data refreshed!</p>
</div>
<?php
}
/**
* The message that is displayed on error of Simian data refresh
*/
function husdson_admin_refresh_error()
{
?>
<div class="notice notice-error is-dismissible">
<p>Error. Simian data was not refreshed. Have you set the Simian API key?</p>
</div>
<?php
}
/**
* Capture data from Simian API and save it to Video posts
*/
function simian_refresh_media()
{
$api_key = get_field("simian_api_key", "option");
$api_url = get_field("simian_api_url", "option");
$curl = Crawler::getCurl();
curl_setopt($curl, CURLOPT_URL, $api_url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, [
"auth_token" => $api_key,
"output_format" => "json",
]);
$response = curl_exec($curl);
simian_store_video_posts($response);
if ($response) {
return true;
} else {
return false;
}
}
/**
* Insert videos from Simian API as post objects
*/
function simian_store_video_posts($media)
{
$media = json_decode($media);
if (
isset($media->root) &&
isset($media->root->media) &&
!empty($media->root->media)
) {
$sim_ids = [];
foreach ($media->root->media as $one_media) {
// Query video post by simian ID
$args = [
"meta_query" => [
[
"key" => "simian_id",
"value" => $one_media->id,
],
],
"post_type" => "videos",
"posts_per_page" => "1",
];
$posts = get_posts($args);
// If no such posts, insert one
if (!$posts) {
$post_id = wp_insert_post(
wp_slash([
"post_title" => wp_strip_all_tags($one_media->title),
"post_content" => $one_media->credits->brand,
"post_status" => "publish",
"post_author" => 1,
"post_type" => "videos",
])
);
if ($post_id == 0) {
die("Error inserting video post");
}
update_post_meta($post_id, "simian_id", $one_media->id);
// Save all Simian data
// SEE https://developer.wordpress.org/plugins/metadata/managing-post-metadata/#workaround
$encoded_meta = wp_slash(wp_json_encode($one_media));
update_post_meta($post_id, "simian_data", $encoded_meta);
simian_import_local_credits($one_media->credits, $post_id);
} else {
simian_import_local_credits($one_media->credits, $posts[0]->ID);
// Update meta data in case Simian has changed (new credits etc)
$encoded_meta = wp_slash(wp_json_encode($one_media));
update_post_meta($posts[0]->ID, "simian_data", $encoded_meta);
}
}
// Iterate each media object to collect all Simian IDs
$api_videos = [];
foreach ($media->root->media as $one_media) {
$api_videos[] = intval($one_media->id);
}
// Now check all Video Posts to match to API, delete Videos that aren't in Simian anymore.
$args = [
"post_type" => "videos",
"posts_per_page" => -1,
];
$video_posts = get_posts($args);
foreach ($video_posts as $video_post) {
// If Video Post doesn't exist in Simian anymore, trash it
if (!in_array(intval($simian_id), $api_videos)) {
wp_delete_post($video_post->ID);
continue;
}
// If post doesn't have a Simian ID saved, trash it.
$simian_id = get_post_meta($video_post->ID, "simian_id", true);
if (!$simian_id) {
wp_delete_post($video_post->ID);
continue;
}
// If post doesn't have Simian Data saved, trash it.
$simian_data = get_post_meta($video_post->ID, "simian_data", true);
if (!$simian_data) {
wp_delete_post($video_post->ID);
continue;
}
}
}
}
/**
* Import or update credits from Simian API
*/
function simian_import_local_credits($simian_credits, $post_id)
{
$local_credits = get_field("video_credit", $post_id);
if (empty($local_credits)) {
foreach ($simian_credits as $key => $value):
$k = str_replace("_", " ", $key);
$row = [
"title" => ucwords($k),
"name" => $value,
];
add_row("video_credit", $row, $post_id);
endforeach;
}
}
/*
* Add the sync button to the admin bar at top of WP dashboard
*/
function simian_sync_toolbar_item($wp_admin_bar)
{
$title = '
<span class="simian-download" title="Click to download data from Simian."><span class="dashicons dashicons-download"></span> Download from Simian</span>
';
$args = [
"id" => "simian-download-button",
"title" => $title,
"href" =>
admin_url() . "edit.php?post_type=videos&simian_refresh_media",
"meta" => [
"class" => "simian-download-button",
],
];
$wp_admin_bar->add_node($args);
}
add_action("admin_bar_menu", "simian_sync_toolbar_item", 999);
/*
* Add some CSS to the admin so that the download button looks good.
*/
function custom_styles()
{
echo '<style>
#wpadminbar .simian-download .dashicons {
font-family: "dashicons";
font-size: 20px;
line-height: 32px;
}
</style>';
}
add_action('admin_head', 'custom_styles');
/**
* Add a WP-GQL field for the Simian Data JSON meta field.
* SEE https://developer.wordpress.org/plugins/metadata/managing-post-metadata/#workaround
*/
function simian_data_field()
{
register_graphql_field('VideoPost', 'simianData', [
'type' => 'String',
'resolve' => function ($post) {
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$content = get_post_meta($post->databaseId, "simian_data", true);
return !empty($content) ? $content : null;
},
]);
}
add_action('graphql_register_types', 'simian_data_field');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment