xref: /plugin/combo/action/metacanonical.php (revision 3dc080c1e74460aa398543295210a94cd2594980)
1007225e5Sgerardnico<?php
2007225e5Sgerardnico
3c3437056SNickeau
4*3dc080c1Sgerardnicouse ComboStrap\ExceptionComboNotFound;
571f916b9Sgerardnicouse ComboStrap\Page;
6*3dc080c1Sgerardnicouse ComboStrap\Site;
7007225e5Sgerardnico
8007225e5Sgerardnico/**
9*3dc080c1Sgerardnico * Add all canonical HTML metadata
10*3dc080c1Sgerardnico *
11*3dc080c1Sgerardnico * In 1.14. we keep the name of the class with canonical to be able to update
12*3dc080c1Sgerardnico * Above 1.15, in a release branch, you can just modify it
13007225e5Sgerardnico */
14c3437056SNickeauclass action_plugin_combo_metacanonical
15007225e5Sgerardnico{
16007225e5Sgerardnico
17007225e5Sgerardnico
18*3dc080c1Sgerardnico    const APPLE_MOBILE_WEB_APP_TITLE_META = "apple-mobile-web-app-title";
19*3dc080c1Sgerardnico    const APPLICATION_NAME_META = "application-name";
20*3dc080c1Sgerardnico
21007225e5Sgerardnico    public function register(Doku_Event_Handler $controller)
22007225e5Sgerardnico    {
2385e82846SNickeau        /**
2485e82846SNickeau         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
2585e82846SNickeau         */
26*3dc080c1Sgerardnico        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'htmlHeadMetadataProcessing', array());
27c3437056SNickeau
28c3437056SNickeau
29007225e5Sgerardnico    }
30007225e5Sgerardnico
31*3dc080c1Sgerardnico
32*3dc080c1Sgerardnico    function htmlHeadMetadataProcessing($event)
33007225e5Sgerardnico    {
34007225e5Sgerardnico
355f891b7eSNickeau        global $ID;
365f891b7eSNickeau        if (empty($ID)) {
375f891b7eSNickeau            // $_SERVER['SCRIPT_NAME']== "/lib/exe/mediamanager.php"
389da76789Sgerardnico            // $ID is null
399da76789Sgerardnico            return;
409da76789Sgerardnico        }
419da76789Sgerardnico
4285e82846SNickeau        $page = Page::createPageFromId($ID);
43007225e5Sgerardnico        /**
44*3dc080c1Sgerardnico         * No metadata for slot page
45007225e5Sgerardnico         */
464cadd4f8SNickeau        if ($page->isSecondarySlot()) {
47007225e5Sgerardnico            return;
48007225e5Sgerardnico        }
49007225e5Sgerardnico
50007225e5Sgerardnico        /**
51*3dc080c1Sgerardnico         * Add the canonical metadata value
52007225e5Sgerardnico         */
53*3dc080c1Sgerardnico        $this->canonicalHeadMetadata($event, $page);
54007225e5Sgerardnico        /**
55*3dc080c1Sgerardnico         * Add the app name value
56*3dc080c1Sgerardnico         */
57*3dc080c1Sgerardnico        $this->appNameMetadata($event, $page);
58*3dc080c1Sgerardnico
59*3dc080c1Sgerardnico    }
60*3dc080c1Sgerardnico
61*3dc080c1Sgerardnico    /**
62*3dc080c1Sgerardnico     * Dokuwiki has already a canonical methodology
63*3dc080c1Sgerardnico     * https://www.dokuwiki.org/canonical
64*3dc080c1Sgerardnico     *
65*3dc080c1Sgerardnico     */
66*3dc080c1Sgerardnico    private function canonicalHeadMetadata($event, Page $page)
67*3dc080c1Sgerardnico    {
68*3dc080c1Sgerardnico
69*3dc080c1Sgerardnico        /**
70*3dc080c1Sgerardnico         * Where do we pick the canonical URL
71007225e5Sgerardnico         * Canonical from meta
72007225e5Sgerardnico         *
73007225e5Sgerardnico         * FYI: The creation of the link was extracted from
74007225e5Sgerardnico         * {@link wl()} that call {@link idfilter()} that performs just a replacement
75007225e5Sgerardnico         * Calling the wl function will not work because
76007225e5Sgerardnico         * {@link wl()} use the constant DOKU_URL that is set before any test via getBaseURL(true)
77007225e5Sgerardnico         */
78c3437056SNickeau        $canonicalUrl = $page->getAbsoluteCanonicalUrl();
79007225e5Sgerardnico
80007225e5Sgerardnico        /**
81007225e5Sgerardnico         * Replace the meta entry
82007225e5Sgerardnico         *
83007225e5Sgerardnico         * First search the key of the meta array
84007225e5Sgerardnico         */
85007225e5Sgerardnico        $canonicalKey = "";
86007225e5Sgerardnico        $canonicalRelArray = array("rel" => "canonical", "href" => $canonicalUrl);
87007225e5Sgerardnico        foreach ($event->data['link'] as $key => $link) {
88007225e5Sgerardnico            if ($link["rel"] == "canonical") {
89007225e5Sgerardnico                $canonicalKey = $key;
90007225e5Sgerardnico            }
91007225e5Sgerardnico        }
92007225e5Sgerardnico        if ($canonicalKey != "") {
93007225e5Sgerardnico            // Update
94007225e5Sgerardnico            $event->data['link'][$canonicalKey] = $canonicalRelArray;
95007225e5Sgerardnico        } else {
96007225e5Sgerardnico            // Add
97007225e5Sgerardnico            $event->data['link'][] = $canonicalRelArray;
98007225e5Sgerardnico        }
99007225e5Sgerardnico
100007225e5Sgerardnico        /**
101007225e5Sgerardnico         * Add the Og canonical meta
102007225e5Sgerardnico         * https://developers.facebook.com/docs/sharing/webmasters/getting-started/versioned-link/
103007225e5Sgerardnico         */
104007225e5Sgerardnico        $canonicalOgKeyKey = "";
105007225e5Sgerardnico        $canonicalPropertyKey = "og:url";
106007225e5Sgerardnico        $canonicalOgArray = array("property" => $canonicalPropertyKey, "content" => $canonicalUrl);
107ebdc69ceSgerardnico        // Search if the canonical property is already present
108007225e5Sgerardnico        foreach ($event->data['meta'] as $key => $meta) {
109ebdc69ceSgerardnico            if (array_key_exists("property", $meta)) {
110ebdc69ceSgerardnico                /**
111ebdc69ceSgerardnico                 * We may have several properties
112ebdc69ceSgerardnico                 */
113007225e5Sgerardnico                if ($meta["property"] == $canonicalPropertyKey) {
114007225e5Sgerardnico                    $canonicalOgKeyKey = $key;
115007225e5Sgerardnico                }
116007225e5Sgerardnico            }
117ebdc69ceSgerardnico        }
118007225e5Sgerardnico        if ($canonicalOgKeyKey != "") {
119007225e5Sgerardnico            // Update
120007225e5Sgerardnico            $event->data['meta'][$canonicalOgKeyKey] = $canonicalOgArray;
121007225e5Sgerardnico        } else {
122007225e5Sgerardnico            // Add
123007225e5Sgerardnico            $event->data['meta'][] = $canonicalOgArray;
124007225e5Sgerardnico        }
125*3dc080c1Sgerardnico    }
126*3dc080c1Sgerardnico
127*3dc080c1Sgerardnico    /**
128*3dc080c1Sgerardnico     * Add the following meta
129*3dc080c1Sgerardnico     * <meta name="apple-mobile-web-app-title" content="appName">
130*3dc080c1Sgerardnico     * <meta name="application-name" content="appName">
131*3dc080c1Sgerardnico     *
132*3dc080c1Sgerardnico     * @param $event
133*3dc080c1Sgerardnico     * @param Page $page
134*3dc080c1Sgerardnico     * @return void
135*3dc080c1Sgerardnico     */
136*3dc080c1Sgerardnico    private function appNameMetadata($event, Page $page)
137*3dc080c1Sgerardnico    {
138*3dc080c1Sgerardnico        $applicationName = Site::getName();
139*3dc080c1Sgerardnico
140*3dc080c1Sgerardnico
141*3dc080c1Sgerardnico        $applicationMetaNameValues = [
142*3dc080c1Sgerardnico            self::APPLE_MOBILE_WEB_APP_TITLE_META,
143*3dc080c1Sgerardnico            self::APPLICATION_NAME_META
144*3dc080c1Sgerardnico        ];
145*3dc080c1Sgerardnico        $metaNameKeyProperty = "name";
146*3dc080c1Sgerardnico        foreach ($applicationMetaNameValues as $applicationNameValue){
147*3dc080c1Sgerardnico
148*3dc080c1Sgerardnico            $appMobileWebAppTitle = array($metaNameKeyProperty => $applicationNameValue, "content" => $applicationName);;
149*3dc080c1Sgerardnico            try {
150*3dc080c1Sgerardnico                $metaKey = $this->getMetaArrayIndex($metaNameKeyProperty, $applicationNameValue, $event->data['meta']);
151*3dc080c1Sgerardnico                // Update
152*3dc080c1Sgerardnico                $event->data['meta'][$metaKey] = $appMobileWebAppTitle;
153*3dc080c1Sgerardnico            } catch (ExceptionComboNotFound $e) {
154*3dc080c1Sgerardnico                // Add
155*3dc080c1Sgerardnico                $event->data['meta'][] = $appMobileWebAppTitle;
156*3dc080c1Sgerardnico            }
157*3dc080c1Sgerardnico        }
158*3dc080c1Sgerardnico
159007225e5Sgerardnico
160007225e5Sgerardnico    }
161007225e5Sgerardnico
162*3dc080c1Sgerardnico    /**
163*3dc080c1Sgerardnico     * @throws ExceptionComboNotFound
164*3dc080c1Sgerardnico     */
165*3dc080c1Sgerardnico    private function getMetaArrayIndex(string $key, string $value, $metas)
166*3dc080c1Sgerardnico    {
167*3dc080c1Sgerardnico        // Search if the canonical property is already present
168*3dc080c1Sgerardnico        foreach ($metas as $key => $meta) {
169*3dc080c1Sgerardnico            if (array_key_exists($key, $meta)) {
170*3dc080c1Sgerardnico                /**
171*3dc080c1Sgerardnico                 * We may have several properties
172*3dc080c1Sgerardnico                 */
173*3dc080c1Sgerardnico                if ($meta[$key] == $value) {
174*3dc080c1Sgerardnico                    return $key;
175*3dc080c1Sgerardnico                }
176*3dc080c1Sgerardnico            }
177*3dc080c1Sgerardnico        }
178*3dc080c1Sgerardnico        throw new ExceptionComboNotFound(`The meta key $key with the value $value was not found`);
179*3dc080c1Sgerardnico    }
180*3dc080c1Sgerardnico
181*3dc080c1Sgerardnico
182007225e5Sgerardnico}
183