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