xref: /plugin/combo/action/metacanonical.php (revision 977ce05d19d8dab0a70c9a27f8da0b7039299e82)
1<?php
2
3
4use ComboStrap\ExceptionComboNotFound;
5use ComboStrap\Page;
6use ComboStrap\Site;
7
8/**
9 * Add all canonical HTML metadata
10 *
11 * In 1.14. we keep the name of the class with canonical to be able to update
12 * Above 1.15, in a release branch, you can just modify it
13 */
14class action_plugin_combo_metacanonical
15{
16
17
18    const APPLE_MOBILE_WEB_APP_TITLE_META = "apple-mobile-web-app-title";
19    const APPLICATION_NAME_META = "application-name";
20
21    public function register(Doku_Event_Handler $controller)
22    {
23        /**
24         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
25         */
26        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'htmlHeadMetadataProcessing', array());
27
28
29    }
30
31
32    function htmlHeadMetadataProcessing($event)
33    {
34
35        global $ID;
36        if (empty($ID)) {
37            // $_SERVER['SCRIPT_NAME']== "/lib/exe/mediamanager.php"
38            // $ID is null
39            return;
40        }
41
42        $page = Page::createPageFromId($ID);
43        /**
44         * No metadata for slot page
45         */
46        if ($page->isSecondarySlot()) {
47            return;
48        }
49
50        /**
51         * Add the canonical metadata value
52         */
53        $this->canonicalHeadMetadata($event, $page);
54        /**
55         * Add the app name value
56         */
57        $this->appNameMetadata($event, $page);
58
59    }
60
61    /**
62     * Dokuwiki has already a canonical methodology
63     * https://www.dokuwiki.org/canonical
64     *
65     */
66    private function canonicalHeadMetadata($event, Page $page)
67    {
68
69        /**
70         * Where do we pick the canonical URL
71         * Canonical from meta
72         *
73         * FYI: The creation of the link was extracted from
74         * {@link wl()} that call {@link idfilter()} that performs just a replacement
75         * Calling the wl function will not work because
76         * {@link wl()} use the constant DOKU_URL that is set before any test via getBaseURL(true)
77         */
78        $canonicalUrl = $page->getAbsoluteCanonicalUrl();
79
80        /**
81         * Replace the meta entry
82         *
83         * First search the key of the meta array
84         */
85        $canonicalKey = "";
86        $canonicalRelArray = array("rel" => "canonical", "href" => $canonicalUrl);
87        foreach ($event->data['link'] as $key => $link) {
88            if ($link["rel"] == "canonical") {
89                $canonicalKey = $key;
90            }
91        }
92        if ($canonicalKey != "") {
93            // Update
94            $event->data['link'][$canonicalKey] = $canonicalRelArray;
95        } else {
96            // Add
97            $event->data['link'][] = $canonicalRelArray;
98        }
99
100        /**
101         * Add the Og canonical meta
102         * https://developers.facebook.com/docs/sharing/webmasters/getting-started/versioned-link/
103         */
104        $canonicalOgKeyKey = "";
105        $canonicalPropertyKey = "og:url";
106        $canonicalOgArray = array("property" => $canonicalPropertyKey, "content" => $canonicalUrl);
107        // Search if the canonical property is already present
108        foreach ($event->data['meta'] as $key => $meta) {
109            if (array_key_exists("property", $meta)) {
110                /**
111                 * We may have several properties
112                 */
113                if ($meta["property"] == $canonicalPropertyKey) {
114                    $canonicalOgKeyKey = $key;
115                }
116            }
117        }
118        if ($canonicalOgKeyKey != "") {
119            // Update
120            $event->data['meta'][$canonicalOgKeyKey] = $canonicalOgArray;
121        } else {
122            // Add
123            $event->data['meta'][] = $canonicalOgArray;
124        }
125    }
126
127    /**
128     * Add the following meta
129     * <meta name="apple-mobile-web-app-title" content="appName">
130     * <meta name="application-name" content="appName">
131     *
132     * @param $event
133     * @param Page $page
134     * @return void
135     */
136    private function appNameMetadata($event, Page $page)
137    {
138        $applicationName = Site::getName();
139
140
141        $applicationMetaNameValues = [
142            self::APPLE_MOBILE_WEB_APP_TITLE_META,
143            self::APPLICATION_NAME_META
144        ];
145        $metaNameKeyProperty = "name";
146        foreach ($applicationMetaNameValues as $applicationNameValue){
147
148            $appMobileWebAppTitle = array($metaNameKeyProperty => $applicationNameValue, "content" => $applicationName);;
149            try {
150                $metaKey = $this->getMetaArrayIndex($metaNameKeyProperty, $applicationNameValue, $event->data['meta']);
151                // Update
152                $event->data['meta'][$metaKey] = $appMobileWebAppTitle;
153            } catch (ExceptionComboNotFound $e) {
154                // Add
155                $event->data['meta'][] = $appMobileWebAppTitle;
156            }
157        }
158
159
160    }
161
162    /**
163     * @throws ExceptionComboNotFound
164     */
165    private function getMetaArrayIndex(string $keyToSearch, string $keyValueToSearch, $metas)
166    {
167        // Search if the canonical property is already present
168        foreach ($metas as $metaKey => $metaValue) {
169            if (array_key_exists($keyToSearch, $metaValue)) {
170                /**
171                 * We may have several properties
172                 */
173                if ($metaValue[$keyToSearch] == $keyValueToSearch) {
174                    return $metaKey;
175                }
176            }
177        }
178        throw new ExceptionComboNotFound("The meta key {$keyToSearch} with the value {$keyValueToSearch} was not found");
179    }
180
181
182}
183