15f891b7eSNickeau<?php 25f891b7eSNickeau 3*c3437056SNickeaurequire_once(__DIR__ . '/../ComboStrap/PluginUtility.php'); 4*c3437056SNickeau 51fa8c418SNickeauuse ComboStrap\DokuPath; 61fa8c418SNickeauuse ComboStrap\Image; 75f891b7eSNickeauuse ComboStrap\LogUtility; 8*c3437056SNickeauuse ComboStrap\Mime; 95f891b7eSNickeauuse ComboStrap\Page; 10*c3437056SNickeauuse ComboStrap\PageImage; 11*c3437056SNickeauuse ComboStrap\PageImageUsage; 12*c3437056SNickeauuse ComboStrap\PageType; 13*c3437056SNickeauuse ComboStrap\PluginUtility; 145f891b7eSNickeauuse ComboStrap\Site; 155f891b7eSNickeauuse ComboStrap\StringUtility; 165f891b7eSNickeau 175f891b7eSNickeau 18*c3437056SNickeau 195f891b7eSNickeau 205f891b7eSNickeau/** 215f891b7eSNickeau * 225f891b7eSNickeau * For the canonical meta, see {@link action_plugin_combo_metacanonical} 235f891b7eSNickeau * 245f891b7eSNickeau * Inspiration, reference: 255f891b7eSNickeau * https://developers.facebook.com/docs/sharing/webmasters 265f891b7eSNickeau * https://github.com/twbs/bootstrap/blob/v4-dev/site/layouts/partials/social.html 275f891b7eSNickeau * https://github.com/mprins/dokuwiki-plugin-socialcards/blob/master/action.php 285f891b7eSNickeau */ 295f891b7eSNickeauclass action_plugin_combo_metafacebook extends DokuWiki_Action_Plugin 305f891b7eSNickeau{ 315f891b7eSNickeau 325f891b7eSNickeau const FACEBOOK_APP_ID = "486120022012342"; 335f891b7eSNickeau 345f891b7eSNickeau /** 355f891b7eSNickeau * The image 365f891b7eSNickeau */ 375f891b7eSNickeau const CONF_DEFAULT_FACEBOOK_IMAGE = "defaultFacebookImage"; 385f891b7eSNickeau 395f891b7eSNickeau 405f891b7eSNickeau const CANONICAL = "facebook"; 415f891b7eSNickeau 425f891b7eSNickeau 435f891b7eSNickeau function __construct() 445f891b7eSNickeau { 455f891b7eSNickeau // enable direct access to language strings 465f891b7eSNickeau // ie $this->lang 475f891b7eSNickeau $this->setupLocale(); 485f891b7eSNickeau } 495f891b7eSNickeau 505f891b7eSNickeau public function register(Doku_Event_Handler $controller) 515f891b7eSNickeau { 525f891b7eSNickeau $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaFacebookProcessing', array()); 535f891b7eSNickeau } 545f891b7eSNickeau 555f891b7eSNickeau /** 565f891b7eSNickeau * 575f891b7eSNickeau * @param $event 585f891b7eSNickeau */ 595f891b7eSNickeau function metaFacebookProcessing($event) 605f891b7eSNickeau { 615f891b7eSNickeau 625f891b7eSNickeau global $ID; 635f891b7eSNickeau if (empty($ID)) { 645f891b7eSNickeau // $ID is null for media 655f891b7eSNickeau return; 665f891b7eSNickeau } 675f891b7eSNickeau 685f891b7eSNickeau 6985e82846SNickeau $page = Page::createPageFromId($ID); 70f788f694Sgerardnico if (!$page->exists()) { 71dd39a644Sgerardnico return; 72dd39a644Sgerardnico } 7321913ab3SNickeau 745f891b7eSNickeau /** 755f891b7eSNickeau * No social for bars 765f891b7eSNickeau */ 77531e725cSNickeau if ($page->isSlot()) { 785f891b7eSNickeau return; 795f891b7eSNickeau } 805f891b7eSNickeau 815f891b7eSNickeau 825f891b7eSNickeau /** 835f891b7eSNickeau * "og:url" is already created in the {@link action_plugin_combo_metacanonical} 845f891b7eSNickeau * "og:description" is already created in the {@link action_plugin_combo_metadescription} 855f891b7eSNickeau */ 865f891b7eSNickeau $facebookMeta = array( 87*c3437056SNickeau "og:title" => StringUtility::truncateString($page->getTitleOrDefault(), 70) 885f891b7eSNickeau ); 89f788f694Sgerardnico $descriptionOrElseDokuWiki = $page->getDescriptionOrElseDokuWiki(); 90f788f694Sgerardnico if (!empty($descriptionOrElseDokuWiki)) { 91f788f694Sgerardnico // happens in test with document without content 92f788f694Sgerardnico $facebookMeta["og:description"] = $descriptionOrElseDokuWiki; 93f788f694Sgerardnico } 945f891b7eSNickeau 955f891b7eSNickeau $title = Site::getTitle(); 965f891b7eSNickeau if (!empty($title)) { 975f891b7eSNickeau $facebookMeta["og:site_name"] = $title; 985f891b7eSNickeau } 995f891b7eSNickeau 1005f891b7eSNickeau /** 1015f891b7eSNickeau * Type of page 1025f891b7eSNickeau */ 103*c3437056SNickeau $pageType = $page->getTypeOrDefault(); 104*c3437056SNickeau switch ($pageType) { 105*c3437056SNickeau case PageType::ARTICLE_TYPE: 1065f891b7eSNickeau // https://ogp.me/#type_article 10785e82846SNickeau $facebookMeta["article:published_time"] = $page->getPublishedElseCreationTime()->format(DATE_ISO8601); 108*c3437056SNickeau $modifiedTime = $page->getModifiedTimeOrDefault(); 109*c3437056SNickeau if ($modifiedTime !== null) { 11085e82846SNickeau $facebookMeta["article:modified_time"] = $modifiedTime->format(DATE_ISO8601); 11185e82846SNickeau } 112*c3437056SNickeau $facebookMeta["og:type"] = $pageType; 113*c3437056SNickeau break; 114*c3437056SNickeau default: 115*c3437056SNickeau // The default facebook value 116*c3437056SNickeau $facebookMeta["og:type"] = PageType::WEBSITE_TYPE; 117*c3437056SNickeau break; 1185f891b7eSNickeau } 1195f891b7eSNickeau 120*c3437056SNickeau 1215f891b7eSNickeau /** 1221fa8c418SNickeau * @var Image[] 1235f891b7eSNickeau */ 124*c3437056SNickeau $facebookImages = $page->getImagesOrDefaultForTheFollowingUsages([PageImageUsage::FACEBOOK, PageImageUsage::SOCIAL, PageImageUsage::ALL]); 1255f891b7eSNickeau if (empty($facebookImages)) { 1261fa8c418SNickeau $defaultFacebookImage = PluginUtility::getConfValue(self::CONF_DEFAULT_FACEBOOK_IMAGE); 1275f891b7eSNickeau if (!empty($defaultFacebookImage)) { 1281fa8c418SNickeau DokuPath::addRootSeparatorIfNotPresent($defaultFacebookImage); 129*c3437056SNickeau $image = Image::createImageFromId($defaultFacebookImage); 1305f891b7eSNickeau if ($image->exists()) { 1315f891b7eSNickeau $facebookImages[] = $image; 1325f891b7eSNickeau } else { 1331fa8c418SNickeau if ($defaultFacebookImage != ":logo-facebook.png") { 1345f891b7eSNickeau LogUtility::msg("The default facebook image ($defaultFacebookImage) does not exist", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1355f891b7eSNickeau } 1365f891b7eSNickeau } 1375f891b7eSNickeau } 1385f891b7eSNickeau } 1395f891b7eSNickeau if (!empty($facebookImages)) { 14021913ab3SNickeau 14121913ab3SNickeau /** 14221913ab3SNickeau * One of image/jpeg, image/gif or image/png 14321913ab3SNickeau * As stated here: https://developers.facebook.com/docs/sharing/webmasters#images 14421913ab3SNickeau **/ 145*c3437056SNickeau $facebookMime = [Mime::JPEG, Mime::GIF, Mime::PNG]; 1465f891b7eSNickeau foreach ($facebookImages as $facebookImage) { 1475f891b7eSNickeau 148*c3437056SNickeau if (!in_array($facebookImage->getPath()->getMime()->toString(), $facebookMime)) { 14921913ab3SNickeau continue; 15021913ab3SNickeau } 15121913ab3SNickeau 1521fa8c418SNickeau /** @var Image $facebookImage */ 1531fa8c418SNickeau if (!($facebookImage->isRaster())) { 1541fa8c418SNickeau LogUtility::msg("Internal: The image ($facebookImage) is not a raster image and this should not be the case for facebook", LogUtility::LVL_MSG_ERROR); 15521913ab3SNickeau continue; 15621913ab3SNickeau } 15721913ab3SNickeau 1585f891b7eSNickeau if (!$facebookImage->exists()) { 1595f891b7eSNickeau LogUtility::msg("The image ($facebookImage) does not exist and was not added", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1605f891b7eSNickeau } else { 1615f891b7eSNickeau 1625f891b7eSNickeau $toSmall = false; 1635f891b7eSNickeau if ($facebookImage->isAnalyzable()) { 1645f891b7eSNickeau 1655f891b7eSNickeau // There is a minimum size constraint of 200px by 200px 1661fa8c418SNickeau if ($facebookImage->getIntrinsicWidth() < 200) { 1675f891b7eSNickeau $toSmall = true; 1685f891b7eSNickeau } else { 1691fa8c418SNickeau $facebookMeta["og:image:width"] = $facebookImage->getIntrinsicWidth(); 1701fa8c418SNickeau if ($facebookImage->getIntrinsicHeight() < 200) { 1715f891b7eSNickeau $toSmall = true; 1725f891b7eSNickeau } else { 1731fa8c418SNickeau $facebookMeta["og:image:height"] = $facebookImage->getIntrinsicHeight(); 1745f891b7eSNickeau } 1755f891b7eSNickeau } 1765f891b7eSNickeau } 1775f891b7eSNickeau 1785f891b7eSNickeau if ($toSmall) { 1791fa8c418SNickeau $message = "The facebook image ($facebookImage) is too small (" . $facebookImage->getIntrinsicWidth() . " x " . $facebookImage->getIntrinsicHeight() . "). The minimum size constraint is 200px by 200px"; 180*c3437056SNickeau if ( 181*c3437056SNickeau $facebookImage->getPath()->toAbsolutePath()->toString() 182*c3437056SNickeau !== 183*c3437056SNickeau $page->getFirstImage()->getPath()->toAbsolutePath()->toString() 184*c3437056SNickeau ) { 1855f891b7eSNickeau LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 1865f891b7eSNickeau } else { 1875f891b7eSNickeau LogUtility::log2BrowserConsole($message); 1885f891b7eSNickeau } 1895f891b7eSNickeau } 1905f891b7eSNickeau 1915f891b7eSNickeau 1925f891b7eSNickeau /** 1935f891b7eSNickeau * We may don't known the dimensions 1945f891b7eSNickeau */ 1955f891b7eSNickeau if (!$toSmall) { 196*c3437056SNickeau $mime = $facebookImage->getPath()->getMime()->toString(); 1975f891b7eSNickeau if (!empty($mime)) { 198*c3437056SNickeau $facebookMeta["og:image:type"] = $mime; 1995f891b7eSNickeau } 20021913ab3SNickeau $facebookMeta["og:image"] = $facebookImage->getAbsoluteUrl(); 2015f891b7eSNickeau // One image only 2025f891b7eSNickeau break; 2035f891b7eSNickeau } 2045f891b7eSNickeau } 2055f891b7eSNickeau 2065f891b7eSNickeau } 2075f891b7eSNickeau } 2085f891b7eSNickeau 2095f891b7eSNickeau 2105f891b7eSNickeau $facebookMeta["fb:app_id"] = self::FACEBOOK_APP_ID; 2115f891b7eSNickeau 2121fa8c418SNickeau $facebookDefaultLocale = "en_US"; 2131fa8c418SNickeau $locale = $page->getLocale($facebookDefaultLocale); 2141fa8c418SNickeau $facebookMeta["og:locale"] = $locale; 2155f891b7eSNickeau 2165f891b7eSNickeau 2175f891b7eSNickeau /** 2185f891b7eSNickeau * Add the properties 2195f891b7eSNickeau */ 2205f891b7eSNickeau foreach ($facebookMeta as $property => $content) { 2215f891b7eSNickeau $event->data['meta'][] = array("property" => $property, "content" => $content); 2225f891b7eSNickeau } 2235f891b7eSNickeau 2245f891b7eSNickeau 2255f891b7eSNickeau } 2265f891b7eSNickeau 2275f891b7eSNickeau} 228