Passed
Push — master ( 72fe55...4d626e )
by Mark
01:41 queued 12s
created

handleTplMetaheaderOutput()   F

Complexity

Conditions 13
Paths 385

Size

Total Lines 181

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 181
rs 2.7766
c 0
b 0
f 0
cc 13
nc 385
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
/**
19
 * DokuWiki Plugin socialcards (Action Component).
20
 *
21
 * @license BSD license
22
 * @author  Mark C. Prins <[email protected]>
23
 */
24
25
class action_plugin_socialcards extends DokuWiki_Action_Plugin {
26
27
    /**
28
     * Register our callback for the TPL_METAHEADER_OUTPUT event.
29
     *
30
     * @param $controller Doku_Event_Handler
31
     * @see DokuWiki_Action_Plugin::register()
32
     */
33
    public function register(Doku_Event_Handler $controller): void {
34
        $controller->register_hook(
35
            'TPL_METAHEADER_OUTPUT',
36
            'BEFORE',
37
            $this,
38
            'handleTplMetaheaderOutput'
39
        );
40
    }
41
42
    /**
43
     * Retrieve metadata and add to the head of the page using appropriate meta
44
     * tags unless the page does not exist.
45
     *
46
     * @param Doku_Event $event the DokuWiki event. $event->data is a two-dimensional
47
     *                          array of all meta headers. The keys are meta, link and script.
48
     * @param mixed      $param the parameters passed to register_hook when this
49
     *                          handler was registered (not used)
50
     *
51
     * @global array     $INFO
52
     * @global string    $ID    page id
53
     * @global array     $conf  global wiki configuration
54
     * @see http://www.dokuwiki.org/devel:event:tpl_metaheader_output
55
     */
56
    public function handleTplMetaheaderOutput(Doku_Event $event, $param): void {
57
        global $ID, $conf, $INFO;
58
59
        if(!page_exists($ID)) {
60
            return;
61
        }
62
63
        // twitter card, see https://dev.twitter.com/cards/markup
64
        // creat a summary card, see https://dev.twitter.com/cards/types/summary
65
        $event->data['meta'][] = array(
66
            'name'    => 'twitter:card',
67
            'content' => "summary",
68
        );
69
70
        $event->data['meta'][] = array(
71
            'name'    => 'twitter:site',
72
            'content' => $this->getConf('twitterName'),
73
        );
74
75
        $event->data['meta'][] = array(
76
            'name'    => 'twitter:title',
77
            'content' => p_get_metadata($ID, 'title', true),
78
        );
79
80
        $desc = p_get_metadata($ID, 'description', true);
81
        if(!empty($desc)) {
82
            $desc                  = str_replace("\n", " ", $desc['abstract']);
83
            $event->data['meta'][] = array(
84
                'name'    => 'twitter:description',
85
                'content' => $desc,
86
            );
87
        }
88
89
        if($this->getConf('twitterUserName') !== '') {
90
            $event->data['meta'][] = array(
91
                'name'    => 'twitter:creator',
92
                'content' => $this->getConf('twitterUserName'),
93
            );
94
        }
95
96
        $event->data['meta'][] = array(
97
            'name'    => 'twitter:image',
98
            'content' => $this->getImage(),
99
        );
100
        $event->data['meta'][] = array(
101
            'name'    => 'twitter:image:alt',
102
            'content' => $this->getImageAlt(),
103
        );
104
105
        // opengraph, see http://ogp.me/
106
        //
107
        // to make this work properly the template should be modified adding the
108
        // namespaces for a (x)html 4 template make html tag:
109
        //
110
        // <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="nl" lang="nl"
111
        //       xmlns:og="http://ogp.me/ns#" xmlns:fb="http://ogp.me/ns/fb#"
112
        //       xmlns:article="http://ogp.me/ns/article#" xmlns:place="http://ogp.me/ns/place#">
113
        //
114
        // and for a (x)html 5 template make head tag:
115
        //
116
        // <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#
117
        //    article: http://ogp.me/ns/article# place: http://ogp.me/ns/place#">
118
119
        // og namespace http://ogp.me/ns#
120
        $event->data['meta'][] = array(
121
            'property' => 'og:locale',
122
            'content'  => $this->getConf('languageTerritory'),
123
        );
124
        $event->data['meta'][] = array(
125
            'property' => 'og:site_name',
126
            'content'  => $conf['title'],
127
        );
128
        $event->data['meta'][] = array(
129
            'property' => 'og:url',
130
            'content'  => wl($ID, '', true),
131
        );
132
        $event->data['meta'][] = array(
133
            'property' => 'og:title',
134
            'content'  => p_get_metadata($ID, 'title', true),
135
        );
136
        if(!empty($desc)) {
137
            $event->data['meta'][] = array(
138
                'property' => 'og:description',
139
                'content'  => $desc,
140
            );
141
        }
142
        $event->data['meta'][] = array(
143
            'property' => 'og:type',
144
            'content'  => "article",
145
        );
146
        $ogImage               = $this->getImage();
147
        $secure                = strpos($ogImage, 'https') === 0 ? ':secure_url' : '';
148
        $event->data['meta'][] = array(
149
            'property' => 'og:image' . $secure,
150
            'content'  => $ogImage,
151
        );
152
153
        // article namespace http://ogp.me/ns/article#
154
        $_dates                = p_get_metadata($ID, 'date', true);
155
        $event->data['meta'][] = array(
156
            'property' => 'article:published_time',
157
            'content'  => dformat($_dates['created']),
158
        );
159
        $event->data['meta'][] = array(
160
            'property' => 'article:modified_time',
161
            'content'  => dformat($_dates['modified']),
162
        );
163
        $event->data['meta'][] = array(
164
            'property' => 'article:author',
165
            'content'  => $INFO['editor'],
166
        );
167
//        $event->data['meta'][] = array(
168
//            'property' => 'article:author',
169
//            'content'  => p_get_metadata($ID, 'creator', true),
170
//        );
171
//        $event->data['meta'][] = array(
172
//            'property' => 'article:author',
173
//            'content'  => p_get_metadata($ID, 'user', true),
174
//        );
175
        $_subject = p_get_metadata($ID, 'subject', true);
176
        if(!empty($_subject)) {
177
            if(!is_array($_subject)) {
178
                $_subject = array($_subject);
179
            }
180
            foreach($_subject as $tag) {
181
                $event->data['meta'][] = array(
182
                    'property' => 'article:tag',
183
                    'content'  => $tag,
184
                );
185
            }
186
        }
187
188
        // place namespace http://ogp.me/ns/place#
189
        $geotags = p_get_metadata($ID, 'geo', true);
190
        $lat     = $geotags['lat'];
191
        $lon     = $geotags['lon'];
192
        if(!(empty($lat) && empty($lon))) {
193
            $event->data['meta'][] = array(
194
                'property' => 'place:location:latitude',
195
                'content'  => $lat,
196
            );
197
            $event->data['meta'][] = array(
198
                'property' => 'place:location:longitude',
199
                'content'  => $lon,
200
            );
201
        }
202
        // see https://developers.facebook.com/docs/opengraph/property-types/#geopoint
203
        $alt = $geotags['alt'];
204
        if(!empty($alt)) {
205
            // facebook expects feet...
206
            $alt *= 3.2808;
207
            $event->data['meta'][] = array(
208
                'property' => 'place:location:altitude',
209
                'content'  => $alt,
210
            );
211
        }
212
213
        /* these are not valid for the GeoPoint type..
214
        $region    = $geotags['region'];
215
        $country   = $geotags['country'];
216
        $placename = $geotags['placename'];
217
        if(!empty($region)) {
218
            $event->data['meta'][] = array('property' => 'place:location:region', 'content' => $region,);
219
        }
220
        if(!empty($placename)) {
221
            $event->data['meta'][] = array('property' => 'place:location:locality', 'content' => $placename,);
222
        }
223
        if(!empty($country)) {
224
            $event->data['meta'][] = array('property' => 'place:location:country-name', 'content' => $country,);
225
        }
226
        */
227
228
        // optional facebook app ID
229
        $appId = $this->getConf('fbAppId');
230
        if(!empty($appId)) {
231
            $event->data['meta'][] = array(
232
                'property' => 'fb:app_id',
233
                'content'  => $appId,
234
            );
235
        }
236
    }
237
238
    /**
239
     * Gets the canonical image path for this page.
240
     *
241
     * @return string the url to the image to use for this page
242
     * @global string $ID page id
243
     */
244
    private function getImage(): string {
245
        global $ID;
246
        $rel = p_get_metadata($ID, 'relation', true);
247
        $img = $rel['firstimage'];
248
249
        if(empty($img)) {
250
            $img = $this->getConf('fallbackImage');
251
            if(strpos($img, "http") === 0) {
252
                // don't use ml() as this results in a HTTP redirect after
253
                //   hitting the wiki making the card image fail.
254
                return $img;
255
            }
256
        }
257
258
        return ml($img, array(), true, '&amp;', true);
259
    }
260
261
    /**
262
     * Gets the alt text for this page image.
263
     *
264
     * @return string alt text
265
     * @global string $ID page id
266
     */
267
    private function getImageAlt(): string  {
268
        global $ID;
269
        $rel   = p_get_metadata($ID, 'relation', true);
270
        $imgID = $rel['firstimage'];
271
        $alt   = "";
272
273
        if(!empty($imgID)) {
274
            require_once(DOKU_INC . 'inc/JpegMeta.php');
275
            $jpegmeta = new JpegMeta(mediaFN($imgID));
276
            $tags     = array(
277
                'IPTC.Caption',
278
                'EXIF.UserComment',
279
                'EXIF.TIFFImageDescription',
280
                'EXIF.TIFFUserComment',
281
                'IPTC.Headline',
282
                'Xmp.dc:title'
283
            );
284
            $alt      = media_getTag($tags, $jpegmeta, "");
285
        }
286
        return htmlspecialchars($alt);
287
    }
288
}
289