15f891b7eSNickeau<?php 25f891b7eSNickeau 3*1fa8c418SNickeauuse ComboStrap\DokuPath; 4*1fa8c418SNickeauuse ComboStrap\Image; 521913ab3SNickeauuse ComboStrap\RasterImageLink; 623723136Sgerardnicouse ComboStrap\MediaLink; 75f891b7eSNickeauuse ComboStrap\LogUtility; 85f891b7eSNickeauuse ComboStrap\MetadataUtility; 95f891b7eSNickeauuse ComboStrap\PluginUtility; 105f891b7eSNickeauuse ComboStrap\Page; 115f891b7eSNickeauuse ComboStrap\Site; 125f891b7eSNickeauuse ComboStrap\StringUtility; 135f891b7eSNickeau 145f891b7eSNickeauif (!defined('DOKU_INC')) die(); 155f891b7eSNickeau 1637748cd8SNickeaurequire_once(__DIR__ . '/../ComboStrap/Site.php'); 1737748cd8SNickeaurequire_once(__DIR__ . '/../ComboStrap/RasterImageLink.php'); 185f891b7eSNickeau 195f891b7eSNickeau/** 205f891b7eSNickeau * 215f891b7eSNickeau * For the canonical meta, see {@link action_plugin_combo_metacanonical} 225f891b7eSNickeau * 235f891b7eSNickeau * Inspiration, reference: 245f891b7eSNickeau * https://developers.facebook.com/docs/sharing/webmasters 255f891b7eSNickeau * https://github.com/twbs/bootstrap/blob/v4-dev/site/layouts/partials/social.html 265f891b7eSNickeau * https://github.com/mprins/dokuwiki-plugin-socialcards/blob/master/action.php 275f891b7eSNickeau */ 285f891b7eSNickeauclass action_plugin_combo_metafacebook extends DokuWiki_Action_Plugin 295f891b7eSNickeau{ 305f891b7eSNickeau 315f891b7eSNickeau const FACEBOOK_APP_ID = "486120022012342"; 325f891b7eSNickeau 335f891b7eSNickeau /** 345f891b7eSNickeau * The image 355f891b7eSNickeau */ 365f891b7eSNickeau const CONF_DEFAULT_FACEBOOK_IMAGE = "defaultFacebookImage"; 375f891b7eSNickeau 385f891b7eSNickeau 395f891b7eSNickeau const CANONICAL = "facebook"; 405f891b7eSNickeau 415f891b7eSNickeau 425f891b7eSNickeau function __construct() 435f891b7eSNickeau { 445f891b7eSNickeau // enable direct access to language strings 455f891b7eSNickeau // ie $this->lang 465f891b7eSNickeau $this->setupLocale(); 475f891b7eSNickeau } 485f891b7eSNickeau 495f891b7eSNickeau public function register(Doku_Event_Handler $controller) 505f891b7eSNickeau { 515f891b7eSNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaFacebookProcessing', array()); 525f891b7eSNickeau } 535f891b7eSNickeau 545f891b7eSNickeau /** 555f891b7eSNickeau * 565f891b7eSNickeau * @param $event 575f891b7eSNickeau */ 585f891b7eSNickeau function metaFacebookProcessing($event) 595f891b7eSNickeau { 605f891b7eSNickeau 615f891b7eSNickeau global $ID; 625f891b7eSNickeau if (empty($ID)) { 635f891b7eSNickeau // $ID is null for media 645f891b7eSNickeau return; 655f891b7eSNickeau } 665f891b7eSNickeau 675f891b7eSNickeau 6885e82846SNickeau $page = Page::createPageFromId($ID); 69f788f694Sgerardnico if (!$page->exists()) { 70dd39a644Sgerardnico return; 71dd39a644Sgerardnico } 7221913ab3SNickeau 735f891b7eSNickeau /** 745f891b7eSNickeau * No social for bars 755f891b7eSNickeau */ 76531e725cSNickeau if ($page->isSlot()) { 775f891b7eSNickeau return; 785f891b7eSNickeau } 795f891b7eSNickeau 805f891b7eSNickeau 815f891b7eSNickeau /** 825f891b7eSNickeau * "og:url" is already created in the {@link action_plugin_combo_metacanonical} 835f891b7eSNickeau * "og:description" is already created in the {@link action_plugin_combo_metadescription} 845f891b7eSNickeau */ 855f891b7eSNickeau $facebookMeta = array( 86f788f694Sgerardnico "og:title" => StringUtility::truncateString($page->getTitleNotEmpty(), 70) 875f891b7eSNickeau ); 88f788f694Sgerardnico $descriptionOrElseDokuWiki = $page->getDescriptionOrElseDokuWiki(); 89f788f694Sgerardnico if (!empty($descriptionOrElseDokuWiki)) { 90f788f694Sgerardnico // happens in test with document without content 91f788f694Sgerardnico $facebookMeta["og:description"] = $descriptionOrElseDokuWiki; 92f788f694Sgerardnico } 935f891b7eSNickeau 945f891b7eSNickeau $title = Site::getTitle(); 955f891b7eSNickeau if (!empty($title)) { 965f891b7eSNickeau $facebookMeta["og:site_name"] = $title; 975f891b7eSNickeau } 985f891b7eSNickeau 995f891b7eSNickeau /** 1005f891b7eSNickeau * Type of page 1015f891b7eSNickeau */ 1025f891b7eSNickeau $ogType = $page->getType(); 1035f891b7eSNickeau if (!empty($ogType)) { 1045f891b7eSNickeau $facebookMeta["og:type"] = $ogType; 1055f891b7eSNickeau } else { 1065f891b7eSNickeau // The default facebook value 1075f891b7eSNickeau $facebookMeta["og:type"] = Page::WEBSITE_TYPE; 1085f891b7eSNickeau } 1095f891b7eSNickeau 1105f891b7eSNickeau if ($ogType == Page::ARTICLE_TYPE) { 1115f891b7eSNickeau // https://ogp.me/#type_article 11285e82846SNickeau $facebookMeta["article:published_time"] = $page->getPublishedElseCreationTime()->format(DATE_ISO8601); 11385e82846SNickeau $modifiedTime = $page->getModifiedTime(); 11485e82846SNickeau if ($modifiedTime != null) { 11585e82846SNickeau $facebookMeta["article:modified_time"] = $modifiedTime->format(DATE_ISO8601); 11685e82846SNickeau } 1175f891b7eSNickeau } 1185f891b7eSNickeau 1195f891b7eSNickeau /** 120*1fa8c418SNickeau * @var Image[] 1215f891b7eSNickeau */ 12223723136Sgerardnico $facebookImages = $page->getLocalImageSet(); 1235f891b7eSNickeau if (empty($facebookImages)) { 124*1fa8c418SNickeau $defaultFacebookImage = PluginUtility::getConfValue(self::CONF_DEFAULT_FACEBOOK_IMAGE); 1255f891b7eSNickeau if (!empty($defaultFacebookImage)) { 126*1fa8c418SNickeau DokuPath::addRootSeparatorIfNotPresent($defaultFacebookImage); 127*1fa8c418SNickeau $image = Image::createImageFromAbsolutePath($defaultFacebookImage); 1285f891b7eSNickeau if ($image->exists()) { 1295f891b7eSNickeau $facebookImages[] = $image; 1305f891b7eSNickeau } else { 131*1fa8c418SNickeau if ($defaultFacebookImage != ":logo-facebook.png") { 1325f891b7eSNickeau LogUtility::msg("The default facebook image ($defaultFacebookImage) does not exist", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1335f891b7eSNickeau } 1345f891b7eSNickeau } 1355f891b7eSNickeau } 1365f891b7eSNickeau } 1375f891b7eSNickeau if (!empty($facebookImages)) { 13821913ab3SNickeau 13921913ab3SNickeau /** 14021913ab3SNickeau * One of image/jpeg, image/gif or image/png 14121913ab3SNickeau * As stated here: https://developers.facebook.com/docs/sharing/webmasters#images 14221913ab3SNickeau **/ 14321913ab3SNickeau $facebookMime = ["image/jpeg", "image/gif", "image/png"]; 1445f891b7eSNickeau foreach ($facebookImages as $facebookImage) { 1455f891b7eSNickeau 14621913ab3SNickeau if (!in_array($facebookImage->getMime(), $facebookMime)) { 14721913ab3SNickeau continue; 14821913ab3SNickeau } 14921913ab3SNickeau 150*1fa8c418SNickeau /** @var Image $facebookImage */ 151*1fa8c418SNickeau if (!($facebookImage->isRaster())) { 152*1fa8c418SNickeau LogUtility::msg("Internal: The image ($facebookImage) is not a raster image and this should not be the case for facebook", LogUtility::LVL_MSG_ERROR); 15321913ab3SNickeau continue; 15421913ab3SNickeau } 15521913ab3SNickeau 1565f891b7eSNickeau if (!$facebookImage->exists()) { 1575f891b7eSNickeau LogUtility::msg("The image ($facebookImage) does not exist and was not added", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1585f891b7eSNickeau } else { 1595f891b7eSNickeau 1605f891b7eSNickeau $toSmall = false; 1615f891b7eSNickeau if ($facebookImage->isAnalyzable()) { 1625f891b7eSNickeau 1635f891b7eSNickeau // There is a minimum size constraint of 200px by 200px 164*1fa8c418SNickeau if ($facebookImage->getIntrinsicWidth() < 200) { 1655f891b7eSNickeau $toSmall = true; 1665f891b7eSNickeau } else { 167*1fa8c418SNickeau $facebookMeta["og:image:width"] = $facebookImage->getIntrinsicWidth(); 168*1fa8c418SNickeau if ($facebookImage->getIntrinsicHeight() < 200) { 1695f891b7eSNickeau $toSmall = true; 1705f891b7eSNickeau } else { 171*1fa8c418SNickeau $facebookMeta["og:image:height"] = $facebookImage->getIntrinsicHeight(); 1725f891b7eSNickeau } 1735f891b7eSNickeau } 1745f891b7eSNickeau } 1755f891b7eSNickeau 1765f891b7eSNickeau if ($toSmall) { 177*1fa8c418SNickeau $message = "The facebook image ($facebookImage) is too small (" . $facebookImage->getIntrinsicWidth() . " x " . $facebookImage->getIntrinsicHeight() . "). The minimum size constraint is 200px by 200px"; 1785f891b7eSNickeau if ($facebookImage->getId() != $page->getFirstImage()->getId()) { 1795f891b7eSNickeau LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1805f891b7eSNickeau } else { 1815f891b7eSNickeau LogUtility::log2BrowserConsole($message); 1825f891b7eSNickeau } 1835f891b7eSNickeau } 1845f891b7eSNickeau 1855f891b7eSNickeau 1865f891b7eSNickeau /** 1875f891b7eSNickeau * We may don't known the dimensions 1885f891b7eSNickeau */ 1895f891b7eSNickeau if (!$toSmall) { 1905f891b7eSNickeau $mime = $facebookImage->getMime(); 1915f891b7eSNickeau if (!empty($mime)) { 1925f891b7eSNickeau $facebookMeta["og:image:type"] = $mime[1]; 1935f891b7eSNickeau } 19421913ab3SNickeau $facebookMeta["og:image"] = $facebookImage->getAbsoluteUrl(); 1955f891b7eSNickeau // One image only 1965f891b7eSNickeau break; 1975f891b7eSNickeau } 1985f891b7eSNickeau } 1995f891b7eSNickeau 2005f891b7eSNickeau } 2015f891b7eSNickeau } 2025f891b7eSNickeau 2035f891b7eSNickeau 2045f891b7eSNickeau $facebookMeta["fb:app_id"] = self::FACEBOOK_APP_ID; 2055f891b7eSNickeau 206*1fa8c418SNickeau $facebookDefaultLocale = "en_US"; 207*1fa8c418SNickeau $locale = $page->getLocale($facebookDefaultLocale); 208*1fa8c418SNickeau $facebookMeta["og:locale"] = $locale; 2095f891b7eSNickeau 2105f891b7eSNickeau 2115f891b7eSNickeau /** 2125f891b7eSNickeau * Add the properties 2135f891b7eSNickeau */ 2145f891b7eSNickeau foreach ($facebookMeta as $property => $content) { 2155f891b7eSNickeau $event->data['meta'][] = array("property" => $property, "content" => $content); 2165f891b7eSNickeau } 2175f891b7eSNickeau 2185f891b7eSNickeau 2195f891b7eSNickeau } 2205f891b7eSNickeau 2215f891b7eSNickeau} 222