Completed
Pull Request — master (#19)
by Mark
02:21
created

action.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * Copyright (c) 2013-2016 Mark C. Prins <[email protected]>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
if (!defined('DOKU_INC')){
19
	die();
20
}
21
if (!defined('DOKU_PLUGIN')) {
22
	define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
23
}
24
25
require_once DOKU_PLUGIN . 'action.php';
26
require_once(DOKU_INC.'inc/JpegMeta.php');
27
/**
28
 * DokuWiki Plugin socialcards (Action Component).
29
 *
30
 * @license BSD license
31
 * @author  Mark C. Prins <[email protected]>
32
 */
33
class action_plugin_socialcards extends DokuWiki_Action_Plugin {
34
35
	/**
36
	 * Register our callback for the TPL_METAHEADER_OUTPUT event.
37
	 *
38
	 * @param $controller Doku_Event_Handler
39
	 * @see DokuWiki_Action_Plugin::register()
40
	 */
41
	public function register(Doku_Event_Handler $controller) {
42
		$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this,
43
				'handle_tpl_metaheader_output');
44
	}
45
46
	/**
47
	 * Retrieve metadata and add to the head of the page using appropriate meta
48
	 * tags unless the page does not exist.
49
	 *
50
	 * @global string $ID page id
51
	 * @global array $conf global wiki configuration
52
	 * @global array $INFO
53
	 * @param Doku_Event $event the DokuWiki event. $event->data is a two-dimensional
54
	 *             array of all meta headers. The keys are meta, link and script.
55
	 * @param mixed $param the parameters passed to register_hook when this
56
	 *             handler was registered (not used)
57
	 *
58
	 * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output
59
	 */
60
	public function handle_tpl_metaheader_output(Doku_Event $event, $param) {
61
		global $ID, $conf, $INFO;
62
63
		if (!page_exists($ID)) { return; }
64
65
		// twitter card, see https://dev.twitter.com/cards/markup
66
		// creat a summary card, see https://dev.twitter.com/cards/types/summary
67
		$event->data['meta'][] = array('name' => 'twitter:card',
68
				'content' => "summary",);
69
70
		$event->data['meta'][] = array('name' => 'twitter:site',
71
				'content' => $this->getConf('twitterName'),);
72
73
		$event->data['meta'][] = array('name' => 'twitter:title',
74
				'content' => p_get_metadata($ID, 'title', true),);
75
76
		$desc = p_get_metadata($ID, 'description', true);
77
		if (!empty($desc)) {
78
			$desc = str_replace("\n", " ", $desc['abstract']);
79
			$event->data['meta'][] = array('name' => 'twitter:description',
80
					'content' => $desc,);
81
		}
82
83
		if ($this->getConf('twitterUserName') != '') {
84
			$event->data['meta'][] = array('name' => 'twitter:creator',
85
				'content' => $this->getConf('twitterUserName'),);
86
		}
87
88
		$event->data['meta'][] = array('name' => 'twitter:image',
89
				'content' => $this->getImage(),);
90
		$event->data['meta'][] = array('name' => 'twitter:image:alt',
91
				'content' => $this->getImageAlt(),);
92
93
		// opengraph, see http://ogp.me/
94
		//
95
		// to make this work properly the template should be modified adding the
96
		// namespaces for a (x)html 4 template make html tag:
97
		//
98
		// <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl"
99
		//       xmlns:og="http://ogp.me/ns#" xmlns:fb="http://ogp.me/ns/fb#"
100
		//       xmlns:article="http://ogp.me/ns/article#" xmlns:place="http://ogp.me/ns/place#">
101
		//
102
		// and for a (x)html 5 template make head tag:
103
		//
104
		// <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#">
105
106
		// og namespace http://ogp.me/ns#
107
		$event->data['meta'][] = array('property' => 'og:locale',
108
				'content' => $this->getConf('languageTerritory'),);
109
		$event->data['meta'][] = array('property' => 'og:site_name',
110
				'content' => $conf['title'],);
111
		$event->data['meta'][] = array('property' => 'og:url',
112
				'content' => wl($ID, '', true),);
113
		$event->data['meta'][] = array('property' => 'og:title',
114
				'content' => p_get_metadata($ID, 'title', true),);
115
		if (!empty($desc)) {
116
			$event->data['meta'][] = array('property' => 'og:description',
117
					'content' => $desc,);
118
		}
119
		$event->data['meta'][] = array('property' => 'og:type',
120
				'content' => "article",);
121
		$ogImage = $this->getImage();
122
		$secure = substr($ogImage, 0, 5) === 'https' ? ':secure_url' : '';
123
		$event->data['meta'][] = array('property' => 'og:image' . $secure,
124
				'content' => $ogImage,);
125
126
		// article namespace http://ogp.me/ns/article#
127
		$_dates = p_get_metadata($ID, 'date', true);
128
		$event->data['meta'][] = array('property' => 'article:published_time',
129
				'content' => dformat($_dates['created']),);
130
		$event->data['meta'][] = array('property' => 'article:modified_time',
131
				'content' => dformat($_dates['modified']),);
132
		$event->data['meta'][] = array('property' => 'article:author',
133
				'content' => $INFO['editor'],);
134
		// $event->data['meta'][] = array('property' => 'article:author','content' => p_get_metadata($ID,'creator',true),);
1 ignored issue
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
135
		// $event->data['meta'][] = array('property' => 'article:author','content' => p_get_metadata($ID,'user',true),);
1 ignored issue
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
136
		$_subject = p_get_metadata($ID, 'subject', true);
137
		if (!empty($_subject)) {
138
			if (!is_array($_subject)) {
139
				$_subject = array($_subject);
140
			}
141
			foreach ($_subject as $tag) {
142
				$event->data['meta'][] = array('property' => 'article:tag',
143
						'content' => $tag,);
144
			}
145
		}
146
147
		// place namespace http://ogp.me/ns/place#
148
		$geotags = p_get_metadata($ID, 'geo', true);
149
		$lat = $geotags['lat'];
150
		$lon = $geotags['lon'];
151
		if (!(empty($lat) && empty($lon))) {
152
			$event->data['meta'][] = array('property' => 'place:location:latitude',
153
					'content' => $lat,);
154
			$event->data['meta'][] = array('property' => 'place:location:longitude',
155
					'content' => $lon,);
156
		}
157
		// see https://developers.facebook.com/docs/opengraph/property-types/#geopoint
158
		$alt = $geotags['alt'];
159
		if (!empty($alt)) {
160
			// facebook expects feet...
161
			$alt = $alt * 3.2808;
162
			$event->data['meta'][] = array('property' => 'place:location:altitude',
163
					'content' => $alt,);
164
		}
165
166
		/* these are not valid for the GeoPoint type..
1 ignored issue
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
167
168
		$region=$geotags['region'];
169
		$country=$geotags['country'];
170
		$placename=$geotags['placename'];
171
		if (!empty($region))    {$event->data['meta'][] = array('property' => 'place:location:region',		'content' => $region,);}
172
		if (!empty($placename)) {$event->data['meta'][] = array('property' => 'place:location:locality',	'content' => $placename,);}
173
		if (!empty($country))   {$event->data['meta'][] = array('property' => 'place:location:country-name','content' => $country,);}
174
		*/
175
176
		// optional facebook app ID
177
		$appId = $this->getConf('fbAppId');
178
		if (!empty($appId)) {
179
			$event->data['meta'][] = array('property' => 'fb:app_id',
180
					'content' => $appId,);
181
		}
182
	}
183
184
	/**
185
	 * Gets the canonical image path for this page.
186
	 *
187
	 * @global string $ID page id
188
	 * @return string the url to the image to use for this page
189
	 */
190
	private function getImage() {
191
		global $ID;
192
		$rel = p_get_metadata($ID, 'relation', true);
193
		$img = $rel['firstimage'];
194
195
		if (empty($img)) {
196
			$img = $this->getConf('fallbackImage');
197
			if (substr($img, 0, 4 ) === "http") {
198
				// don't use ml() as this results in a HTTP redirect after hitting the wiki
199
				return $img;
200
			}
201
		}
202
203
		return ml($img, array(), true, '&amp;', true);
204
	}
205
206
	/**
207
	 * Gets the alt text for this page image.
208
	 *
209
	 * @global string $ID page id
210
	 * @return string alt text
211
	 */
212
	private function getImageAlt() {
213
		global $ID;
214
		$rel = p_get_metadata($ID, 'relation', true);
215
		$imgID = $rel['firstimage'];
216
		$alt = "";
217
218
		if (!empty($imgID)) {
219
			require_once(DOKU_INC.'inc/JpegMeta.php');
220
			$jpegmeta = new JpegMeta(mediaFN($imgID));
221
			$tags = array('IPTC.Caption',
222
							'EXIF.UserComment',
223
							'EXIF.TIFFImageDescription',
224
							'EXIF.TIFFUserComment',
225
							'IPTC.Headline',
226
							'Xmp.dc:title'
227
							);
228
			$alt = media_getTag( $tags,$jpegmeta,"");
229
		}
230
		return htmlspecialchars($alt);
231
	}
232
233
}
234