1<?php 2 3use ComboStrap\Image; 4use ComboStrap\LogUtility; 5use ComboStrap\MetadataUtility; 6use ComboStrap\PluginUtility; 7use ComboStrap\Page; 8use ComboStrap\Site; 9use ComboStrap\StringUtility; 10 11if (!defined('DOKU_INC')) die(); 12 13require_once(__DIR__ . '/../class/Site.php'); 14require_once(__DIR__ . '/../class/Image.php'); 15 16/** 17 * 18 * For the canonical meta, see {@link action_plugin_combo_metacanonical} 19 * 20 * Inspiration, reference: 21 * https://developers.facebook.com/docs/sharing/webmasters 22 * https://github.com/twbs/bootstrap/blob/v4-dev/site/layouts/partials/social.html 23 * https://github.com/mprins/dokuwiki-plugin-socialcards/blob/master/action.php 24 */ 25class action_plugin_combo_metafacebook extends DokuWiki_Action_Plugin 26{ 27 28 const FACEBOOK_APP_ID = "486120022012342"; 29 30 /** 31 * The image 32 */ 33 const CONF_DEFAULT_FACEBOOK_IMAGE = "defaultFacebookImage"; 34 35 36 const CANONICAL = "facebook"; 37 38 39 function __construct() 40 { 41 // enable direct access to language strings 42 // ie $this->lang 43 $this->setupLocale(); 44 } 45 46 public function register(Doku_Event_Handler $controller) 47 { 48 $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaFacebookProcessing', array()); 49 } 50 51 /** 52 * 53 * @param $event 54 */ 55 function metaFacebookProcessing($event) 56 { 57 58 global $ID; 59 if (empty($ID)) { 60 // $ID is null for media 61 return; 62 } 63 64 65 $page = new Page($ID); 66 if(!$page->existInFs()){ 67 return; 68 } 69 /** 70 * No social for bars 71 */ 72 if ($page->isBar()) { 73 return; 74 } 75 76 77 /** 78 * "og:url" is already created in the {@link action_plugin_combo_metacanonical} 79 * "og:description" is already created in the {@link action_plugin_combo_metadescription} 80 */ 81 $facebookMeta = array( 82 "og:title" => StringUtility::truncateString($page->getTitleNotEmpty(), 70), 83 "og:description" => $page->getDescriptionOrElseDokuWiki(), 84 ); 85 86 $title = Site::getTitle(); 87 if (!empty($title)) { 88 $facebookMeta["og:site_name"] = $title; 89 } 90 91 /** 92 * Type of page 93 */ 94 $ogType = $page->getType(); 95 if (!empty($ogType)) { 96 $facebookMeta["og:type"] = $ogType; 97 } else { 98 // The default facebook value 99 $facebookMeta["og:type"] = Page::WEBSITE_TYPE; 100 } 101 102 if ($ogType == Page::ARTICLE_TYPE) { 103 // https://ogp.me/#type_article 104 $facebookMeta["article:published_time"] = date("c", $page->getPublishedElseCreationTimeStamp()); 105 $facebookMeta["article:modified_time"] = date("c", $page->getModifiedTimestamp()); 106 } 107 108 /** 109 * @var Image[] 110 */ 111 $facebookImages = $page->getImageSet(); 112 if (empty($facebookImages)) { 113 $defaultFacebookImage = cleanID(PluginUtility::getConfValue(self::CONF_DEFAULT_FACEBOOK_IMAGE)); 114 if (!empty($defaultFacebookImage)) { 115 $image = new Image($defaultFacebookImage); 116 if ($image->exists()) { 117 $facebookImages[] = $image; 118 } else { 119 if ($defaultFacebookImage != "logo-facebook.png") { 120 LogUtility::msg("The default facebook image ($defaultFacebookImage) does not exist", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 121 } 122 } 123 124 125 } 126 } 127 if (!empty($facebookImages)) { 128 foreach ($facebookImages as $facebookImage) { 129 130 if (!$facebookImage->exists()) { 131 LogUtility::msg("The image ($facebookImage) does not exist and was not added", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 132 } else { 133 134 $toSmall = false; 135 if ($facebookImage->isAnalyzable()) { 136 137 // There is a minimum size constraint of 200px by 200px 138 if ($facebookImage->getWidth() < 200) { 139 $toSmall = true; 140 } else { 141 $facebookMeta["og:image:width"] = $facebookImage->getWidth(); 142 if ($facebookImage->getHeight() < 200) { 143 $toSmall = true; 144 } else { 145 $facebookMeta["og:image:height"] = $facebookImage->getHeight(); 146 } 147 } 148 } 149 150 if ($toSmall) { 151 $message = "The facebook image ($facebookImage) is too small (" . $facebookImage->getWidth() . " x " . $facebookImage->getHeight() . "). The minimum size constraint is 200px by 200px"; 152 if ($facebookImage->getId() != $page->getFirstImage()->getId()) { 153 LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 154 } else { 155 LogUtility::log2BrowserConsole($message); 156 } 157 } 158 159 160 /** 161 * We may don't known the dimensions 162 */ 163 if (!$toSmall) { 164 $mime = $facebookImage->getMime(); 165 if (!empty($mime)) { 166 $facebookMeta["og:image:type"] = $mime[1]; 167 } 168 $facebookMeta["og:image"] = $facebookImage->getUrl(); 169 // One image only 170 break; 171 } 172 } 173 174 } 175 } 176 177 178 $facebookMeta["fb:app_id"] = self::FACEBOOK_APP_ID; 179 180 $lang = $page->getLang(); 181 if (!empty($lang)) { 182 183 $country = $page->getCountry(); 184 if (empty($country)) { 185 $country = $lang; 186 } 187 $facebookMeta["og:locale"] = $lang . "_" . strtoupper($country); 188 189 } else { 190 191 // The Facebook default 192 $facebookMeta["og:locale"] = "en_US"; 193 194 } 195 196 /** 197 * Add the properties 198 */ 199 foreach ($facebookMeta as $property => $content) { 200 $event->data['meta'][] = array("property" => $property, "content" => $content); 201 } 202 203 204 } 205 206} 207