xref: /plugin/combo/action/metacanonical.php (revision 0db54741aa63d46fa1b13c660ec9e66e43aa5e5a)
1007225e5Sgerardnico<?php
2007225e5Sgerardnico
3c3437056SNickeau
43dc080c1Sgerardnicouse ComboStrap\ExceptionComboNotFound;
571f916b9Sgerardnicouse ComboStrap\Page;
63dc080c1Sgerardnicouse ComboStrap\Site;
7007225e5Sgerardnico
8007225e5Sgerardnico/**
93dc080c1Sgerardnico * Add all canonical HTML metadata
103dc080c1Sgerardnico *
113dc080c1Sgerardnico * In 1.14. we keep the name of the class with canonical to be able to update
123dc080c1Sgerardnico * Above 1.15, in a release branch, you can just modify it
13007225e5Sgerardnico */
14c3437056SNickeauclass action_plugin_combo_metacanonical
15007225e5Sgerardnico{
16007225e5Sgerardnico
17007225e5Sgerardnico
183dc080c1Sgerardnico    const APPLE_MOBILE_WEB_APP_TITLE_META = "apple-mobile-web-app-title";
193dc080c1Sgerardnico    const APPLICATION_NAME_META = "application-name";
203dc080c1Sgerardnico
21007225e5Sgerardnico    public function register(Doku_Event_Handler $controller)
22007225e5Sgerardnico    {
2385e82846SNickeau        /**
2485e82846SNickeau         * https://www.dokuwiki.org/devel:event:tpl_metaheader_output
2585e82846SNickeau         */
263dc080c1Sgerardnico        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'htmlHeadMetadataProcessing', array());
27c3437056SNickeau
28c3437056SNickeau
29007225e5Sgerardnico    }
30007225e5Sgerardnico
313dc080c1Sgerardnico
323dc080c1Sgerardnico    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        /**
443dc080c1Sgerardnico         * No metadata for slot page
45007225e5Sgerardnico         */
464cadd4f8SNickeau        if ($page->isSecondarySlot()) {
47007225e5Sgerardnico            return;
48007225e5Sgerardnico        }
49007225e5Sgerardnico
50007225e5Sgerardnico        /**
513dc080c1Sgerardnico         * Add the canonical metadata value
52007225e5Sgerardnico         */
533dc080c1Sgerardnico        $this->canonicalHeadMetadata($event, $page);
54007225e5Sgerardnico        /**
553dc080c1Sgerardnico         * Add the app name value
563dc080c1Sgerardnico         */
573dc080c1Sgerardnico        $this->appNameMetadata($event, $page);
583dc080c1Sgerardnico
593dc080c1Sgerardnico    }
603dc080c1Sgerardnico
613dc080c1Sgerardnico    /**
623dc080c1Sgerardnico     * Dokuwiki has already a canonical methodology
633dc080c1Sgerardnico     * https://www.dokuwiki.org/canonical
643dc080c1Sgerardnico     *
653dc080c1Sgerardnico     */
663dc080c1Sgerardnico    private function canonicalHeadMetadata($event, Page $page)
673dc080c1Sgerardnico    {
683dc080c1Sgerardnico
693dc080c1Sgerardnico        /**
703dc080c1Sgerardnico         * 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        }
1253dc080c1Sgerardnico    }
1263dc080c1Sgerardnico
1273dc080c1Sgerardnico    /**
1283dc080c1Sgerardnico     * Add the following meta
1293dc080c1Sgerardnico     * <meta name="apple-mobile-web-app-title" content="appName">
1303dc080c1Sgerardnico     * <meta name="application-name" content="appName">
1313dc080c1Sgerardnico     *
1323dc080c1Sgerardnico     * @param $event
1333dc080c1Sgerardnico     * @param Page $page
1343dc080c1Sgerardnico     * @return void
1353dc080c1Sgerardnico     */
1363dc080c1Sgerardnico    private function appNameMetadata($event, Page $page)
1373dc080c1Sgerardnico    {
1383dc080c1Sgerardnico        $applicationName = Site::getName();
1393dc080c1Sgerardnico
1403dc080c1Sgerardnico
1413dc080c1Sgerardnico        $applicationMetaNameValues = [
1423dc080c1Sgerardnico            self::APPLE_MOBILE_WEB_APP_TITLE_META,
1433dc080c1Sgerardnico            self::APPLICATION_NAME_META
1443dc080c1Sgerardnico        ];
1453dc080c1Sgerardnico        $metaNameKeyProperty = "name";
1463dc080c1Sgerardnico        foreach ($applicationMetaNameValues as $applicationNameValue){
1473dc080c1Sgerardnico
1483dc080c1Sgerardnico            $appMobileWebAppTitle = array($metaNameKeyProperty => $applicationNameValue, "content" => $applicationName);;
1493dc080c1Sgerardnico            try {
1503dc080c1Sgerardnico                $metaKey = $this->getMetaArrayIndex($metaNameKeyProperty, $applicationNameValue, $event->data['meta']);
1513dc080c1Sgerardnico                // Update
1523dc080c1Sgerardnico                $event->data['meta'][$metaKey] = $appMobileWebAppTitle;
1533dc080c1Sgerardnico            } catch (ExceptionComboNotFound $e) {
1543dc080c1Sgerardnico                // Add
1553dc080c1Sgerardnico                $event->data['meta'][] = $appMobileWebAppTitle;
1563dc080c1Sgerardnico            }
1573dc080c1Sgerardnico        }
1583dc080c1Sgerardnico
159007225e5Sgerardnico
160007225e5Sgerardnico    }
161007225e5Sgerardnico
1623dc080c1Sgerardnico    /**
1633dc080c1Sgerardnico     * @throws ExceptionComboNotFound
1643dc080c1Sgerardnico     */
165*0db54741Sgerardnico    private function getMetaArrayIndex(string $keyToSearch, string $keyValueToSearch, $metas)
1663dc080c1Sgerardnico    {
1673dc080c1Sgerardnico        // Search if the canonical property is already present
168*0db54741Sgerardnico        foreach ($metas as $metaKey => $metaValue) {
169*0db54741Sgerardnico            if (array_key_exists($keyToSearch, $metaValue)) {
1703dc080c1Sgerardnico                /**
1713dc080c1Sgerardnico                 * We may have several properties
1723dc080c1Sgerardnico                 */
173*0db54741Sgerardnico                if ($metaValue[$keyToSearch] == $keyValueToSearch) {
174*0db54741Sgerardnico                    return $metaKey;
1753dc080c1Sgerardnico                }
1763dc080c1Sgerardnico            }
1773dc080c1Sgerardnico        }
178*0db54741Sgerardnico        throw new ExceptionComboNotFound("The meta key {$keyToSearch} with the value {$keyValueToSearch} was not found");
1793dc080c1Sgerardnico    }
1803dc080c1Sgerardnico
1813dc080c1Sgerardnico
182007225e5Sgerardnico}
183