xref: /plugin/socialcards/action.php (revision 156465ee21bf5e3be159ebce923d24f2c937eff6)
1fdb4710bSMark Prins<?php
289906951SMark Prins
3635a5e2dSMark Prins/*
4fdb4710bSMark Prins * Copyright (c) 2013 Mark C. Prins <mprins@users.sf.net>
5fdb4710bSMark Prins *
6fdb4710bSMark Prins * Permission to use, copy, modify, and distribute this software for any
7fdb4710bSMark Prins * purpose with or without fee is hereby granted, provided that the above
8fdb4710bSMark Prins * copyright notice and this permission notice appear in all copies.
9fdb4710bSMark Prins *
10fdb4710bSMark Prins * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11fdb4710bSMark Prins * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12fdb4710bSMark Prins * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13fdb4710bSMark Prins * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14fdb4710bSMark Prins * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15fdb4710bSMark Prins * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16fdb4710bSMark Prins * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17635a5e2dSMark Prins */
18635a5e2dSMark Prins
19ae2f5c78SMark Prins
2089906951SMark Prinsif (!defined('DOKU_INC'))
2189906951SMark Prins	die();
2289906951SMark Prinsif (!defined('DOKU_PLUGIN'))
2389906951SMark Prins	define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
24fdb4710bSMark Prins
25fdb4710bSMark Prinsrequire_once DOKU_PLUGIN . 'action.php';
26ae2f5c78SMark Prins/**
27ae2f5c78SMark Prins * DokuWiki Plugin socialcards (Action Component).
28ae2f5c78SMark Prins *
29ae2f5c78SMark Prins * @license BSD license
30ae2f5c78SMark Prins * @author  Mark C. Prins <mprins@users.sf.net>
31ae2f5c78SMark Prins */
32fdb4710bSMark Prinsclass action_plugin_socialcards extends DokuWiki_Action_Plugin {
33fdb4710bSMark Prins
34ae2f5c78SMark Prins	/**
35ae2f5c78SMark Prins	 * Register our callback for the TPL_METAHEADER_OUTPUT event.
36ae2f5c78SMark Prins	 *
37ae2f5c78SMark Prins	 * @param $controller Doku_Event_Handler
38ae2f5c78SMark Prins	 * @see DokuWiki_Action_Plugin::register()
39ae2f5c78SMark Prins	 */
40ae2f5c78SMark Prins	public function register(Doku_Event_Handler $controller) {
4189906951SMark Prins		$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this,
4289906951SMark Prins				'handle_tpl_metaheader_output');
43fdb4710bSMark Prins	}
44fdb4710bSMark Prins
45fdb4710bSMark Prins	/**
4689906951SMark Prins	 * Retrieve metadata and add to the head of the page using appropriate meta
47*156465eeSMark Prins	 * tags unless the page does not exist.
4889906951SMark Prins	 *
4989906951SMark Prins	 * @global string $ID page id
5089906951SMark Prins	 * @global array $conf global wiki configuration
5189906951SMark Prins	 * @global array $INFO
52fdb4710bSMark Prins	 * @param Doku_Event $event the DokuWiki event. $event->data is a two-dimensional
53fdb4710bSMark Prins	 * array of all meta headers. The keys are meta, link and script.
5489906951SMark Prins	 * @param unknown_type $param the parameters passed to register_hook when this
5589906951SMark Prins	 * handler was registered
5689906951SMark Prins	 *
5789906951SMark Prins	 * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output
58fdb4710bSMark Prins	 */
59fdb4710bSMark Prins	public function handle_tpl_metaheader_output(Doku_Event &$event, $param) {
6089906951SMark Prins		global $ID, $conf, $INFO;
61fdb4710bSMark Prins
62*156465eeSMark Prins		if (!page_exists($ID)) return;
63*156465eeSMark Prins
64fdb4710bSMark Prins		// twitter card, see https://dev.twitter.com/docs/cards
6589906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:card',
6689906951SMark Prins				'content' => "summary",);
6789906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:url',
6889906951SMark Prins				'content' => wl($ID, '', true),);
6989906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:title',
7089906951SMark Prins				'content' => p_get_metadata($ID, 'title', true),);
71aeb704feSMark Prins		$desc = p_get_metadata($ID, 'description', true);
72aeb704feSMark Prins		if (!empty($desc)) {
7389906951SMark Prins			$desc = str_replace("\n", " ", $desc['abstract']);
74fc03d0b3SMark Prins			$event->data['meta'][] = array('name' => 'twitter:description',
7589906951SMark Prins					'content' => $desc,);
76fc03d0b3SMark Prins		}
7789906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:site',
7889906951SMark Prins				'content' => $this->getConf('twitterName'),);
79fdb4710bSMark Prins		//twitter:site:id
8089906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:creator',
8189906951SMark Prins				'content' => $this->getConf('twitterName'),);
82fdb4710bSMark Prins		//twitter:creator:id
8389906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:image',
8489906951SMark Prins				'content' => $this->getImage(),);
8589906951SMark Prins
8689906951SMark Prins		// opengraph, see http://ogp.me/
8789906951SMark Prins		//
8889906951SMark Prins		// to make this work properly the template should be modified adding the
8989906951SMark Prins		// namespaces for a (x)html 4 template make html tag:
9089906951SMark Prins		//
9189906951SMark Prins		// <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl"
9289906951SMark Prins		//		xmlns:og="http://ogp.me/ns#" xmlns:fb="http://ogp.me/ns/fb#"
9389906951SMark Prins		//		xmlns:article="http://ogp.me/ns/article#" xmlns:place="http://ogp.me/ns/place#">
9489906951SMark Prins		//
9589906951SMark Prins		// and for a (x)html 5 template make head tag:
9689906951SMark Prins		//
9789906951SMark Prins		// <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article# place: http://ogp.me/ns/place#">
9889906951SMark Prins
9989906951SMark Prins		// og namespace http://ogp.me/ns#
10089906951SMark Prins		$event->data['meta'][] = array('property' => 'og:locale',
10189906951SMark Prins				'content' => $this->getConf('languageTerritory'),);
10289906951SMark Prins		$event->data['meta'][] = array('property' => 'og:site_name',
10389906951SMark Prins				'content' => $conf['title'],);
10489906951SMark Prins		$event->data['meta'][] = array('property' => 'og:url',
10589906951SMark Prins				'content' => wl($ID, '', true),);
10689906951SMark Prins		$event->data['meta'][] = array('property' => 'og:title',
10789906951SMark Prins				'content' => p_get_metadata($ID, 'title', true),);
10889906951SMark Prins		if (!empty($desc)) {
10989906951SMark Prins			$event->data['meta'][] = array('property' => 'og:description',
11089906951SMark Prins					'content' => $desc,);
111fdb4710bSMark Prins		}
11289906951SMark Prins		$event->data['meta'][] = array('property' => 'og:type',
11389906951SMark Prins				'content' => "article",);
11489906951SMark Prins		$event->data['meta'][] = array('property' => 'og:image',
11589906951SMark Prins				'content' => $this->getImage(),);
11689906951SMark Prins
11789906951SMark Prins		// article namespace http://ogp.me/ns/article#
11889906951SMark Prins		$_dates = p_get_metadata($ID, 'date', true);
11989906951SMark Prins		$event->data['meta'][] = array('property' => 'article:published_time',
12089906951SMark Prins				'content' => dformat($_dates['created']),);
12189906951SMark Prins		$event->data['meta'][] = array('property' => 'article:modified_time',
12289906951SMark Prins				'content' => dformat($_dates['modified']),);
12389906951SMark Prins		$event->data['meta'][] = array('property' => 'article:author',
12489906951SMark Prins				'content' => $INFO['editor'],);
12589906951SMark Prins		// $event->data['meta'][] = array('property' => 'article:author','content' => p_get_metadata($ID,'creator',true),);
12689906951SMark Prins		// $event->data['meta'][] = array('property' => 'article:author','content' => p_get_metadata($ID,'user',true),);
12789906951SMark Prins		$_subject = p_get_metadata($ID, 'subject', true);
12889906951SMark Prins		if (!empty($_subject)) {
12989906951SMark Prins			if (!is_array($_subject)) {
13089906951SMark Prins				$_subject = array($_subject);
13189906951SMark Prins			}
13289906951SMark Prins			foreach ($_subject as $tag) {
13389906951SMark Prins				$event->data['meta'][] = array('property' => 'article:tag',
13489906951SMark Prins						'content' => $tag,);
13589906951SMark Prins			}
13689906951SMark Prins		}
13789906951SMark Prins
13889906951SMark Prins		// place namespace http://ogp.me/ns/place#
13989906951SMark Prins		$geotags = p_get_metadata($ID, 'geo', true);
14089906951SMark Prins		$lat = $geotags['lat'];
14189906951SMark Prins		$lon = $geotags['lon'];
14289906951SMark Prins		if (!(empty($lat) && empty($lon))) {
14389906951SMark Prins			$event->data['meta'][] = array('property' => 'place:location:latitude',
14489906951SMark Prins					'content' => $lat,);
14589906951SMark Prins			$event->data['meta'][] = array('property' => 'place:location:longitude',
14689906951SMark Prins					'content' => $lon,);
147ae2f5c78SMark Prins			// place:location:altitude (string) Altitude of location, facebook wants feet...
14889906951SMark Prins		}
14989906951SMark Prins
150ae2f5c78SMark Prins		/* these are not valid for the GeoPoint type..
151ae2f5c78SMark Prins
15289906951SMark Prins		$region=$geotags['region'];
15389906951SMark Prins		$country=$geotags['country'];
15489906951SMark Prins		$placename=$geotags['placename'];
15589906951SMark Prins		if (!empty($region))    {$event->data['meta'][] = array('property' => 'place:location:region',		'content' => $region,);}
15689906951SMark Prins		if (!empty($placename)) {$event->data['meta'][] = array('property' => 'place:location:locality',	'content' => $placename,);}
15789906951SMark Prins		if (!empty($country))   {$event->data['meta'][] = array('property' => 'place:location:country-name','content' => $country,);}
15889906951SMark Prins		*/
15989906951SMark Prins
16089906951SMark Prins		// optional facebook app ID
16189906951SMark Prins		$appId = $this->getConf('fbAppId');
16289906951SMark Prins		if (!empty($appId)) {
16389906951SMark Prins			$event->data['meta'][] = array('property' => 'fb:app_id',
16489906951SMark Prins					'content' => $appId,);
16589906951SMark Prins		}
16689906951SMark Prins	}
16789906951SMark Prins
16889906951SMark Prins	/**
16989906951SMark Prins	 * Gets the canonical image path for this page.
17089906951SMark Prins	 *
17189906951SMark Prins	 * @global string $ID page id
17289906951SMark Prins	 * @return string the url to the image to use for this page
17389906951SMark Prins	 */
17489906951SMark Prins	private function getImage() {
17589906951SMark Prins		global $ID;
17689906951SMark Prins		$rel = p_get_metadata($ID, 'relation', true);
17789906951SMark Prins		$img = $rel['firstimage'];
178ae2f5c78SMark Prins
179ae2f5c78SMark Prins		if (empty($img)) {
18093bf3c56SMark Prins			$img = $this->getConf('fallbackImage');
18193bf3c56SMark Prins			if (substr($img, 0, 4 ) === "http") {
182ae2f5c78SMark Prins				// don't use ml() as this results in a HTTP redirect after hitting the wiki
18393bf3c56SMark Prins				return $img;
18493bf3c56SMark Prins			}
18593bf3c56SMark Prins		}
186ae2f5c78SMark Prins
187ae2f5c78SMark Prins		return ml($img, array(), true, '&amp;', true);
18889906951SMark Prins	}
18989906951SMark Prins
190fdb4710bSMark Prins}
191