xref: /plugin/socialcards/action.php (revision 89906951ae5990af6f3c5d02a911a009e3c7fb2b)
1fdb4710bSMark Prins<?php
2*89906951SMark 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
19635a5e2dSMark Prins/**
20*89906951SMark Prins * DokuWiki Plugin socialcards (Action Component).
21fdb4710bSMark Prins *
22635a5e2dSMark Prins * @license BSD license
23fdb4710bSMark Prins * @author  Mark C. Prins <mprins@users.sf.net>
24fdb4710bSMark Prins */
25*89906951SMark Prinsif (!defined('DOKU_INC'))
26*89906951SMark Prins	die();
27*89906951SMark Prinsif (!defined('DOKU_PLUGIN'))
28*89906951SMark Prins	define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
29fdb4710bSMark Prins
30fdb4710bSMark Prinsrequire_once DOKU_PLUGIN . 'action.php';
31fdb4710bSMark Prins
32fdb4710bSMark Prinsclass action_plugin_socialcards extends DokuWiki_Action_Plugin {
33fdb4710bSMark Prins
34fdb4710bSMark Prins	public function register(Doku_Event_Handler &$controller) {
35*89906951SMark Prins		$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this,
36*89906951SMark Prins				'handle_tpl_metaheader_output');
37fdb4710bSMark Prins	}
38fdb4710bSMark Prins
39fdb4710bSMark Prins	/**
40*89906951SMark Prins	 * Retrieve metadata and add to the head of the page using appropriate meta
41*89906951SMark Prins	 * tags.
42*89906951SMark Prins	 *
43*89906951SMark Prins	 * @global string $ID page id
44*89906951SMark Prins	 * @global array $conf global wiki configuration
45*89906951SMark Prins	 * @global array $INFO
46fdb4710bSMark Prins	 * @param Doku_Event $event the DokuWiki event. $event->data is a two-dimensional
47fdb4710bSMark Prins	 * array of all meta headers. The keys are meta, link and script.
48*89906951SMark Prins	 * @param unknown_type $param the parameters passed to register_hook when this
49*89906951SMark Prins	 * handler was registered
50*89906951SMark Prins	 *
51*89906951SMark Prins	 * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output
52fdb4710bSMark Prins	 */
53fdb4710bSMark Prins	public function handle_tpl_metaheader_output(Doku_Event &$event, $param) {
54*89906951SMark Prins		global $ID, $conf, $INFO;
55fdb4710bSMark Prins
56fdb4710bSMark Prins		// twitter card, see https://dev.twitter.com/docs/cards
57*89906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:card',
58*89906951SMark Prins				'content' => "summary",);
59*89906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:url',
60*89906951SMark Prins				'content' => wl($ID, '', true),);
61*89906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:title',
62*89906951SMark Prins				'content' => p_get_metadata($ID, 'title', true),);
63aeb704feSMark Prins		$desc = p_get_metadata($ID, 'description', true);
64aeb704feSMark Prins		if (!empty($desc)) {
65*89906951SMark Prins			$desc = str_replace("\n", " ", $desc['abstract']);
66fc03d0b3SMark Prins			$event->data['meta'][] = array('name' => 'twitter:description',
67*89906951SMark Prins					'content' => $desc,);
68fc03d0b3SMark Prins		}
69*89906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:site',
70*89906951SMark Prins				'content' => $this->getConf('twitterName'),);
71fdb4710bSMark Prins		//twitter:site:id
72*89906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:creator',
73*89906951SMark Prins				'content' => $this->getConf('twitterName'),);
74fdb4710bSMark Prins		//twitter:creator:id
75*89906951SMark Prins		$event->data['meta'][] = array('name' => 'twitter:image',
76*89906951SMark Prins				'content' => $this->getImage(),);
77*89906951SMark Prins
78*89906951SMark Prins		// opengraph, see http://ogp.me/
79*89906951SMark Prins		//
80*89906951SMark Prins		// to make this work properly the template should be modified adding the
81*89906951SMark Prins		// namespaces for a (x)html 4 template make html tag:
82*89906951SMark Prins		//
83*89906951SMark Prins		// <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl"
84*89906951SMark Prins		//		xmlns:og="http://ogp.me/ns#" xmlns:fb="http://ogp.me/ns/fb#"
85*89906951SMark Prins		//		xmlns:article="http://ogp.me/ns/article#" xmlns:place="http://ogp.me/ns/place#">
86*89906951SMark Prins		//
87*89906951SMark Prins		// and for a (x)html 5 template make head tag:
88*89906951SMark Prins		//
89*89906951SMark 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#">
90*89906951SMark Prins
91*89906951SMark Prins		// og namespace http://ogp.me/ns#
92*89906951SMark Prins		$event->data['meta'][] = array('property' => 'og:locale',
93*89906951SMark Prins				'content' => $this->getConf('languageTerritory'),);
94*89906951SMark Prins		$event->data['meta'][] = array('property' => 'og:site_name',
95*89906951SMark Prins				'content' => $conf['title'],);
96*89906951SMark Prins		$event->data['meta'][] = array('property' => 'og:url',
97*89906951SMark Prins				'content' => wl($ID, '', true),);
98*89906951SMark Prins		$event->data['meta'][] = array('property' => 'og:title',
99*89906951SMark Prins				'content' => p_get_metadata($ID, 'title', true),);
100*89906951SMark Prins		if (!empty($desc)) {
101*89906951SMark Prins			$event->data['meta'][] = array('property' => 'og:description',
102*89906951SMark Prins					'content' => $desc,);
103fdb4710bSMark Prins		}
104*89906951SMark Prins		$event->data['meta'][] = array('property' => 'og:type',
105*89906951SMark Prins				'content' => "article",);
106*89906951SMark Prins		$event->data['meta'][] = array('property' => 'og:image',
107*89906951SMark Prins				'content' => $this->getImage(),);
108*89906951SMark Prins
109*89906951SMark Prins		// article namespace http://ogp.me/ns/article#
110*89906951SMark Prins		$_dates = p_get_metadata($ID, 'date', true);
111*89906951SMark Prins		$event->data['meta'][] = array('property' => 'article:published_time',
112*89906951SMark Prins				'content' => dformat($_dates['created']),);
113*89906951SMark Prins		$event->data['meta'][] = array('property' => 'article:modified_time',
114*89906951SMark Prins				'content' => dformat($_dates['modified']),);
115*89906951SMark Prins		$event->data['meta'][] = array('property' => 'article:author',
116*89906951SMark Prins				'content' => $INFO['editor'],);
117*89906951SMark Prins		//$event->data['meta'][] = array('property' => 'article:author','content' => p_get_metadata($ID,'creator',true),);
118*89906951SMark Prins		//$event->data['meta'][] = array('property' => 'article:author','content' => p_get_metadata($ID,'user',true),);
119*89906951SMark Prins		$_subject = p_get_metadata($ID, 'subject', true);
120*89906951SMark Prins		if (!empty($_subject)) {
121*89906951SMark Prins			if (!is_array($_subject)) {
122*89906951SMark Prins				$_subject = array($_subject);
123*89906951SMark Prins			}
124*89906951SMark Prins			foreach ($_subject as $tag) {
125*89906951SMark Prins				$event->data['meta'][] = array('property' => 'article:tag',
126*89906951SMark Prins						'content' => $tag,);
127*89906951SMark Prins			}
128*89906951SMark Prins		}
129*89906951SMark Prins
130*89906951SMark Prins		// place namespace http://ogp.me/ns/place#
131*89906951SMark Prins		$geotags = p_get_metadata($ID, 'geo', true);
132*89906951SMark Prins		$lat = $geotags['lat'];
133*89906951SMark Prins		$lon = $geotags['lon'];
134*89906951SMark Prins		if (!(empty($lat) && empty($lon))) {
135*89906951SMark Prins			$event->data['meta'][] = array('property' => 'place:location:latitude',
136*89906951SMark Prins					'content' => $lat,);
137*89906951SMark Prins			$event->data['meta'][] = array('property' => 'place:location:longitude',
138*89906951SMark Prins					'content' => $lon,);
139*89906951SMark Prins		}
140*89906951SMark Prins
141*89906951SMark Prins		/* these may not be valid..
142*89906951SMark Prins		 $region=$geotags['region'];
143*89906951SMark Prins		$country=$geotags['country'];
144*89906951SMark Prins		$placename=$geotags['placename'];
145*89906951SMark Prins		if (!empty($region))    {$event->data['meta'][] = array('property' => 'place:location:region',		'content' => $region,);}
146*89906951SMark Prins		if (!empty($placename)) {$event->data['meta'][] = array('property' => 'place:location:locality',	'content' => $placename,);}
147*89906951SMark Prins		if (!empty($country))   {$event->data['meta'][] = array('property' => 'place:location:country-name','content' => $country,);}
148*89906951SMark Prins		*/
149*89906951SMark Prins
150*89906951SMark Prins		// optional facebook app ID
151*89906951SMark Prins		$appId = $this->getConf('fbAppId');
152*89906951SMark Prins		if (!empty($appId)) {
153*89906951SMark Prins			$event->data['meta'][] = array('property' => 'fb:app_id',
154*89906951SMark Prins					'content' => $appId,);
155*89906951SMark Prins		}
156*89906951SMark Prins	}
157*89906951SMark Prins
158*89906951SMark Prins	/**
159*89906951SMark Prins	 * Gets the canonical image path for this page.
160*89906951SMark Prins	 *
161*89906951SMark Prins	 * @global string $ID page id
162*89906951SMark Prins	 * @return string the url to the image to use for this page
163*89906951SMark Prins	 */
164*89906951SMark Prins	private function getImage() {
165*89906951SMark Prins		global $ID;
166*89906951SMark Prins		$rel = p_get_metadata($ID, 'relation', true);
167*89906951SMark Prins		$img = $rel['firstimage'];
168*89906951SMark Prins		if (!empty($img)) {
169*89906951SMark Prins			return ml($img, array(), true, '&amp;', true);
170*89906951SMark Prins		} else {
171*89906951SMark Prins			return $this->getConf('fallbackImage');
172*89906951SMark Prins		}
173*89906951SMark Prins	}
174*89906951SMark Prins
175fdb4710bSMark Prins}
176