15f891b7eSNickeau<?php 25f891b7eSNickeau 321913ab3SNickeauuse ComboStrap\RasterImageLink; 423723136Sgerardnicouse ComboStrap\MediaLink; 55f891b7eSNickeauuse ComboStrap\LogUtility; 65f891b7eSNickeauuse ComboStrap\MetadataUtility; 75f891b7eSNickeauuse ComboStrap\PluginUtility; 85f891b7eSNickeauuse ComboStrap\Page; 95f891b7eSNickeauuse ComboStrap\Site; 105f891b7eSNickeauuse ComboStrap\StringUtility; 115f891b7eSNickeau 125f891b7eSNickeauif (!defined('DOKU_INC')) die(); 135f891b7eSNickeau 145f891b7eSNickeaurequire_once(__DIR__ . '/../class/Site.php'); 1521913ab3SNickeaurequire_once(__DIR__ . '/../class/RasterImageLink.php'); 165f891b7eSNickeau 175f891b7eSNickeau/** 185f891b7eSNickeau * 195f891b7eSNickeau * For the canonical meta, see {@link action_plugin_combo_metacanonical} 205f891b7eSNickeau * 215f891b7eSNickeau * Inspiration, reference: 225f891b7eSNickeau * https://developers.facebook.com/docs/sharing/webmasters 235f891b7eSNickeau * https://github.com/twbs/bootstrap/blob/v4-dev/site/layouts/partials/social.html 245f891b7eSNickeau * https://github.com/mprins/dokuwiki-plugin-socialcards/blob/master/action.php 255f891b7eSNickeau */ 265f891b7eSNickeauclass action_plugin_combo_metafacebook extends DokuWiki_Action_Plugin 275f891b7eSNickeau{ 285f891b7eSNickeau 295f891b7eSNickeau const FACEBOOK_APP_ID = "486120022012342"; 305f891b7eSNickeau 315f891b7eSNickeau /** 325f891b7eSNickeau * The image 335f891b7eSNickeau */ 345f891b7eSNickeau const CONF_DEFAULT_FACEBOOK_IMAGE = "defaultFacebookImage"; 355f891b7eSNickeau 365f891b7eSNickeau 375f891b7eSNickeau const CANONICAL = "facebook"; 385f891b7eSNickeau 395f891b7eSNickeau 405f891b7eSNickeau function __construct() 415f891b7eSNickeau { 425f891b7eSNickeau // enable direct access to language strings 435f891b7eSNickeau // ie $this->lang 445f891b7eSNickeau $this->setupLocale(); 455f891b7eSNickeau } 465f891b7eSNickeau 475f891b7eSNickeau public function register(Doku_Event_Handler $controller) 485f891b7eSNickeau { 495f891b7eSNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaFacebookProcessing', array()); 505f891b7eSNickeau } 515f891b7eSNickeau 525f891b7eSNickeau /** 535f891b7eSNickeau * 545f891b7eSNickeau * @param $event 555f891b7eSNickeau */ 565f891b7eSNickeau function metaFacebookProcessing($event) 575f891b7eSNickeau { 585f891b7eSNickeau 595f891b7eSNickeau global $ID; 605f891b7eSNickeau if (empty($ID)) { 615f891b7eSNickeau // $ID is null for media 625f891b7eSNickeau return; 635f891b7eSNickeau } 645f891b7eSNickeau 655f891b7eSNickeau 66*85e82846SNickeau $page = Page::createPageFromId($ID); 67f788f694Sgerardnico if (!$page->exists()) { 68dd39a644Sgerardnico return; 69dd39a644Sgerardnico } 7021913ab3SNickeau 715f891b7eSNickeau /** 725f891b7eSNickeau * No social for bars 735f891b7eSNickeau */ 74531e725cSNickeau if ($page->isSlot()) { 755f891b7eSNickeau return; 765f891b7eSNickeau } 775f891b7eSNickeau 785f891b7eSNickeau 795f891b7eSNickeau /** 805f891b7eSNickeau * "og:url" is already created in the {@link action_plugin_combo_metacanonical} 815f891b7eSNickeau * "og:description" is already created in the {@link action_plugin_combo_metadescription} 825f891b7eSNickeau */ 835f891b7eSNickeau $facebookMeta = array( 84f788f694Sgerardnico "og:title" => StringUtility::truncateString($page->getTitleNotEmpty(), 70) 855f891b7eSNickeau ); 86f788f694Sgerardnico $descriptionOrElseDokuWiki = $page->getDescriptionOrElseDokuWiki(); 87f788f694Sgerardnico if (!empty($descriptionOrElseDokuWiki)) { 88f788f694Sgerardnico // happens in test with document without content 89f788f694Sgerardnico $facebookMeta["og:description"] = $descriptionOrElseDokuWiki; 90f788f694Sgerardnico } 915f891b7eSNickeau 925f891b7eSNickeau $title = Site::getTitle(); 935f891b7eSNickeau if (!empty($title)) { 945f891b7eSNickeau $facebookMeta["og:site_name"] = $title; 955f891b7eSNickeau } 965f891b7eSNickeau 975f891b7eSNickeau /** 985f891b7eSNickeau * Type of page 995f891b7eSNickeau */ 1005f891b7eSNickeau $ogType = $page->getType(); 1015f891b7eSNickeau if (!empty($ogType)) { 1025f891b7eSNickeau $facebookMeta["og:type"] = $ogType; 1035f891b7eSNickeau } else { 1045f891b7eSNickeau // The default facebook value 1055f891b7eSNickeau $facebookMeta["og:type"] = Page::WEBSITE_TYPE; 1065f891b7eSNickeau } 1075f891b7eSNickeau 1085f891b7eSNickeau if ($ogType == Page::ARTICLE_TYPE) { 1095f891b7eSNickeau // https://ogp.me/#type_article 110*85e82846SNickeau $facebookMeta["article:published_time"] = $page->getPublishedElseCreationTime()->format(DATE_ISO8601); 111*85e82846SNickeau $modifiedTime = $page->getModifiedTime(); 112*85e82846SNickeau if($modifiedTime!=null) { 113*85e82846SNickeau $facebookMeta["article:modified_time"] = $modifiedTime->format(DATE_ISO8601); 114*85e82846SNickeau } 1155f891b7eSNickeau } 1165f891b7eSNickeau 1175f891b7eSNickeau /** 11823723136Sgerardnico * @var MediaLink[] 1195f891b7eSNickeau */ 12023723136Sgerardnico $facebookImages = $page->getLocalImageSet(); 1215f891b7eSNickeau if (empty($facebookImages)) { 1225f891b7eSNickeau $defaultFacebookImage = cleanID(PluginUtility::getConfValue(self::CONF_DEFAULT_FACEBOOK_IMAGE)); 1235f891b7eSNickeau if (!empty($defaultFacebookImage)) { 124*85e82846SNickeau $image = MediaLink::createMediaLinkFromNonQualifiedPath($defaultFacebookImage); 1255f891b7eSNickeau if ($image->exists()) { 1265f891b7eSNickeau $facebookImages[] = $image; 1275f891b7eSNickeau } else { 1285f891b7eSNickeau if ($defaultFacebookImage != "logo-facebook.png") { 1295f891b7eSNickeau LogUtility::msg("The default facebook image ($defaultFacebookImage) does not exist", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1305f891b7eSNickeau } 1315f891b7eSNickeau } 1325f891b7eSNickeau 1335f891b7eSNickeau 1345f891b7eSNickeau } 1355f891b7eSNickeau } 1365f891b7eSNickeau if (!empty($facebookImages)) { 13721913ab3SNickeau 13821913ab3SNickeau /** 13921913ab3SNickeau * One of image/jpeg, image/gif or image/png 14021913ab3SNickeau * As stated here: https://developers.facebook.com/docs/sharing/webmasters#images 14121913ab3SNickeau **/ 14221913ab3SNickeau $facebookMime = ["image/jpeg", "image/gif", "image/png"]; 1435f891b7eSNickeau foreach ($facebookImages as $facebookImage) { 1445f891b7eSNickeau 14521913ab3SNickeau if (!in_array($facebookImage->getMime(), $facebookMime)) { 14621913ab3SNickeau continue; 14721913ab3SNickeau } 14821913ab3SNickeau 14921913ab3SNickeau /** @var RasterImageLink $facebookImage */ 15021913ab3SNickeau if (!($facebookImage instanceof RasterImageLink)) { 15121913ab3SNickeau LogUtility::msg("Internal: The image ($facebookImage) is not a raster image and this should not be the case for facebook", LogUtility::LVL_MSG_ERROR, "support"); 15221913ab3SNickeau continue; 15321913ab3SNickeau } 15421913ab3SNickeau 1555f891b7eSNickeau if (!$facebookImage->exists()) { 1565f891b7eSNickeau LogUtility::msg("The image ($facebookImage) does not exist and was not added", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1575f891b7eSNickeau } else { 1585f891b7eSNickeau 1595f891b7eSNickeau $toSmall = false; 1605f891b7eSNickeau if ($facebookImage->isAnalyzable()) { 1615f891b7eSNickeau 1625f891b7eSNickeau // There is a minimum size constraint of 200px by 200px 16321913ab3SNickeau if ($facebookImage->getMediaWidth() < 200) { 1645f891b7eSNickeau $toSmall = true; 1655f891b7eSNickeau } else { 16621913ab3SNickeau $facebookMeta["og:image:width"] = $facebookImage->getMediaWidth(); 16721913ab3SNickeau if ($facebookImage->getMediaHeight() < 200) { 1685f891b7eSNickeau $toSmall = true; 1695f891b7eSNickeau } else { 17021913ab3SNickeau $facebookMeta["og:image:height"] = $facebookImage->getMediaHeight(); 1715f891b7eSNickeau } 1725f891b7eSNickeau } 1735f891b7eSNickeau } 1745f891b7eSNickeau 1755f891b7eSNickeau if ($toSmall) { 17621913ab3SNickeau $message = "The facebook image ($facebookImage) is too small (" . $facebookImage->getMediaWidth() . " x " . $facebookImage->getMediaHeight() . "). The minimum size constraint is 200px by 200px"; 1775f891b7eSNickeau if ($facebookImage->getId() != $page->getFirstImage()->getId()) { 1785f891b7eSNickeau LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1795f891b7eSNickeau } else { 1805f891b7eSNickeau LogUtility::log2BrowserConsole($message); 1815f891b7eSNickeau } 1825f891b7eSNickeau } 1835f891b7eSNickeau 1845f891b7eSNickeau 1855f891b7eSNickeau /** 1865f891b7eSNickeau * We may don't known the dimensions 1875f891b7eSNickeau */ 1885f891b7eSNickeau if (!$toSmall) { 1895f891b7eSNickeau $mime = $facebookImage->getMime(); 1905f891b7eSNickeau if (!empty($mime)) { 1915f891b7eSNickeau $facebookMeta["og:image:type"] = $mime[1]; 1925f891b7eSNickeau } 19321913ab3SNickeau $facebookMeta["og:image"] = $facebookImage->getAbsoluteUrl(); 1945f891b7eSNickeau // One image only 1955f891b7eSNickeau break; 1965f891b7eSNickeau } 1975f891b7eSNickeau } 1985f891b7eSNickeau 1995f891b7eSNickeau } 2005f891b7eSNickeau } 2015f891b7eSNickeau 2025f891b7eSNickeau 2035f891b7eSNickeau $facebookMeta["fb:app_id"] = self::FACEBOOK_APP_ID; 2045f891b7eSNickeau 2055f891b7eSNickeau $lang = $page->getLang(); 2065f891b7eSNickeau if (!empty($lang)) { 2075f891b7eSNickeau 2085f891b7eSNickeau $country = $page->getCountry(); 2095f891b7eSNickeau if (empty($country)) { 2105f891b7eSNickeau $country = $lang; 2115f891b7eSNickeau } 2125f891b7eSNickeau $facebookMeta["og:locale"] = $lang . "_" . strtoupper($country); 2135f891b7eSNickeau 2145f891b7eSNickeau } else { 2155f891b7eSNickeau 2165f891b7eSNickeau // The Facebook default 2175f891b7eSNickeau $facebookMeta["og:locale"] = "en_US"; 2185f891b7eSNickeau 2195f891b7eSNickeau } 2205f891b7eSNickeau 2215f891b7eSNickeau /** 2225f891b7eSNickeau * Add the properties 2235f891b7eSNickeau */ 2245f891b7eSNickeau foreach ($facebookMeta as $property => $content) { 2255f891b7eSNickeau $event->data['meta'][] = array("property" => $property, "content" => $content); 2265f891b7eSNickeau } 2275f891b7eSNickeau 2285f891b7eSNickeau 2295f891b7eSNickeau } 2305f891b7eSNickeau 2315f891b7eSNickeau} 232