Completed
Push — master ( 7387e3...3efb31 )
by Mark
02:23
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
        $region=$geotags['region'];
168
        $country=$geotags['country'];
169
        $placename=$geotags['placename'];
170
        if (!empty($region))    {$event->data['meta'][] = array('property' => 'place:location:region',      'content' => $region,);}
171
        if (!empty($placename)) {$event->data['meta'][] = array('property' => 'place:location:locality',    'content' => $placename,);}
172
        if (!empty($country))   {$event->data['meta'][] = array('property' => 'place:location:country-name','content' => $country,);}
173
        */
174
175
        // optional facebook app ID
176
        $appId = $this->getConf('fbAppId');
177
        if (!empty($appId)) {
178
            $event->data['meta'][] = array('property' => 'fb:app_id',
179
                    'content' => $appId,);
180
        }
181
    }
182
183
    /**
184
     * Gets the canonical image path for this page.
185
     *
186
     * @global string $ID page id
187
     * @return string the url to the image to use for this page
188
     */
189
    private function getImage() {
190
        global $ID;
191
        $rel = p_get_metadata($ID, 'relation', true);
192
        $img = $rel['firstimage'];
193
194
        if (empty($img)) {
195
            $img = $this->getConf('fallbackImage');
196
            if (substr($img, 0, 4) === "http") {
197
                // don't use ml() as this results in a HTTP redirect after
198
                //   hitting the wiki making the card image fail.
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