morristech
11/28/2018 - 4:41 PM

WordPress Google Photos embed handler

WordPress Google Photos embed handler

<?php
/*
Plugin Name: Google Photos embed handler
Plugin URI: https://www.faircode.eu/
Description: Google photos embed handler
Version: 0.1
Author: Marcel Bokhorst
Author URI: https://www.faircode.eu/
*/

/*
	Copyright 2016 Marcel Bokhorst

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

add_action('admin_init', 'm66b_embed_admin_init');
add_action('admin_menu', 'm66b_embed_admin_menu');
add_action('init', 'm66b_init_embed_gphotos');

function m66b_embed_admin_init() {
	register_setting(
		'gphotos-embed-options',
		'gphotos-embed-timeout'
	);
	register_setting(
		'gphotos-embed-options',
		'gphotos-embed-cache'
	);
	add_settings_section(
		'gphotos-embed-general-section',
		'General',
		'm66b_embed_general_section_render',
		'gphotos-embed-options'
	);
	add_settings_field(
		'gphotos-embed-timeout',
		'Connection time-out',
		'm66b_embed_connection_timeout_render',
		'gphotos-embed-options',
		'gphotos-embed-general-section'
	);
	add_settings_field(
		'gphotos-embed-cache',
		'Cache time',
		'm66b_embed_cache_time_render',
		'gphotos-embed-options',
		'gphotos-embed-general-section'
	);
}

function m66b_embed_general_section_render() {
}

function m66b_embed_connection_timeout_render() {
	$setting = esc_attr(get_option('gphotos-embed-timeout'));
	echo '<input name="gphotos-embed-timeout" type="text" value="' . $setting . '" /> seconds';
	echo '<p>Default 20 seconds</p>';
}

function m66b_embed_cache_time_render() {
	$setting = esc_attr(get_option('gphotos-embed-cache'));
	echo '<input name="gphotos-embed-cache" type="text" value="' . $setting . '" /> seconds';
	echo '<p>Default 24 hours; -1 disables caching</p>';
}

function m66b_embed_admin_menu() {
	add_options_page(
		'Google Photos',
		'Google Photos',
		'manage_options',
		'gphotos-embed-options',
		'm66b_embed_options_page'
	);
}

function m66b_embed_options_page() {
?>
	<div class="wrap">
		<h1>Google Photos</h1>
		<form method="POST" action="options.php">
		<?php
			settings_fields('gphotos-embed-options');
			do_settings_sections('gphotos-embed-options');
			submit_button();
		?>
		</form>
	</div>
<?php
}

function m66b_init_embed_gphotos() {
	wp_embed_register_handler('m66b_handle_gphotos_embed', '#https\://goo\.gl/photos/(.+)#i', 'm66b_handle_gphotos_embed', 1);
}

/*
	<meta property="og:title" content="Herfst 2016">
	<meta property="og:type" content="google_photos:photo_album">
	<meta property="og:url" content="https://photos.google.com/share/AF1QipMgDv2lQHWV6ExEblT-3DiZpjkLaivhLZfgofb_ebijt5321F1huWMrwi6Bde6YXQ?key=dkpJSWlFLUF2TXFrcmFWeC05VGFiQi02UGJoT1Vn">
	<meta property="og:image" content="https://lh3.googleusercontent.com/3Y-pWKaVuVUkkVcWnpEITJGBqRq2tZRz4uPyUO_U15no9eZSkJPU8W9edIRSRkTkMoHfBXJVzXIC=w600-h315-p-k">
	<meta property="og:image:width" content="600">
	<meta property="og:image:height" content="315">
	<meta property="og:description" content="40 new photos · Album by Marcel Bokhorst">
*/

function m66b_handle_gphotos_embed($matches, $attr, $url, $rawattr) {
	// Check cache
	$transient_name = 'm66b_gp_' . md5($url);
	$cache_time = get_option('gphotos-embed-cache');
	$cache_time = (empty($cache_time) ? 24 * 60 * 60 : $cache_time);
	$meta = ($cache_time < 0 ? false : get_transient($transient_name));
	$cached = ($meta !== false);
	if (!$cached) {
		// Fetch album page
		$timeout = get_option('gphotos-embed-timeout');
		$timeout = (empty($timeout) ? 20 : $timeout);
		$response = wp_safe_remote_get($url, array(
			'timeout' => $timeout,
			'httpversion' => '1.1',
			'sslverify' => true,
			'headers' => array('Accept-Language' => get_bloginfo('language') . ', en;q=0.7, *;q=0.5')
		));
		if (is_wp_error($response) || $response['response']['code'] !== 200)
			return '<a href="' . esc_attr($url) . '">' . esc_html($url) . '</a> error=' . print_r($response, true);

		// Get ogp tags
		libxml_use_internal_errors(true);
		$doc = new DomDocument();
		$doc->loadHTML(mb_convert_encoding($response['body'], 'HTML-ENTITIES', 'UTF-8'));
		$xpath = new DOMXPath($doc);
		$meta = array();
		foreach ($xpath->query('//*/meta[starts-with(@property, \'og:\')]') as $xmeta)
			$meta[$xmeta->getAttribute('property')] = $xmeta->getAttribute('content');

		// Update cache
		if ($cache_time > 0)
			set_transient($transient_name, $meta, $cache_time);
		else
			delete_transient($transient_name);
	}

	// Check for required fields
	if (!isset($meta['og:image']) ||
		(!isset($meta['og:title']) && !isset($meta['og:description'])))
		return '<a href="' . esc_attr($url) . '">' . esc_html($url) . '</a> meta=' . print_r($meta, true);

	// Build title
	$title = (isset($meta['og:title']) ? $meta['og:title'] : null);
	if (isset($meta['og:description']))
		$title .= ($title == null ? '' : ' · ') . $meta['og:description'];

	// Get image size
	$width  = (isset($meta['og:image:width']) ? ' width="' . esc_attr($meta['og:image:width']) . '"' : '');
	$height = (isset($meta['og:image:height']) ? ' height="' . esc_attr($meta['og:image:height']) . '"' : '');

	// Embed image
	return
		'<figure style="text-align: center;">' .
			'<a href="' . esc_attr($url) . '">' .
				'<img src="' . esc_attr($meta['og:image']) . '"' . $width . $height . ' title="' . esc_attr($title) . '" alt="' . esc_attr($title) . '">' .
			'</a>' .
			'<figcaption><a href="' . esc_attr($url) . '">' . $title . '</a></figcaption>' .
			(false ? '<div style="display: none;">' .
				'cached=' . ($cached ? 'true' : 'false') . ':' . $cache_time . PHP_EOL .
				'timeout=' . $timeout . PHP_EOL .
				esc_html(print_r($meta, true)) .
			'</div>' : '') .
		'</figure>';
}

?>