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 67 /** 68 * No social for bars 69 */ 70 if ($page->isBar()) { 71 return; 72 } 73 74 75 /** 76 * "og:url" is already created in the {@link action_plugin_combo_metacanonical} 77 * "og:description" is already created in the {@link action_plugin_combo_metadescription} 78 */ 79 $facebookMeta = array( 80 "og:title" => StringUtility::truncateString($page->getTitleNotEmpty(), 70), 81 "og:description" => $page->getDescription(), 82 ); 83 84 $title = Site::getTitle(); 85 if (!empty($title)) { 86 $facebookMeta["og:site_name"] = $title; 87 } 88 89 /** 90 * Type of page 91 */ 92 $ogType = $page->getType(); 93 if (!empty($ogType)) { 94 $facebookMeta["og:type"] = $ogType; 95 } else { 96 // The default facebook value 97 $facebookMeta["og:type"] = Page::WEBSITE_TYPE; 98 } 99 100 if ($ogType == Page::ARTICLE_TYPE) { 101 // https://ogp.me/#type_article 102 $facebookMeta["article:published_time"] = date("c", $page->getPublishedElseCreationTimeStamp()); 103 $facebookMeta["article:modified_time"] = date("c", $page->getModifiedTimestamp()); 104 } 105 106 /** 107 * @var Image[] 108 */ 109 $facebookImages = $page->getImageSet(); 110 if (empty($facebookImages)) { 111 $defaultFacebookImage = cleanID(PluginUtility::getConfValue(self::CONF_DEFAULT_FACEBOOK_IMAGE)); 112 if (!empty($defaultFacebookImage)) { 113 $image = new Image($defaultFacebookImage); 114 if ($image->exists()) { 115 $facebookImages[] = $image; 116 } else { 117 if ($defaultFacebookImage != "logo-facebook.png") { 118 LogUtility::msg("The default facebook image ($defaultFacebookImage) does not exist", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 119 } 120 } 121 122 123 } 124 } 125 if (!empty($facebookImages)) { 126 foreach ($facebookImages as $facebookImage) { 127 128 if (!$facebookImage->exists()) { 129 LogUtility::msg("The image ($facebookImage) does not exist and was not added", LogUtility::LVL_MSG_ERROR, self::CANONICAL); 130 } else { 131 132 $toSmall = false; 133 if ($facebookImage->isAnalyzable()) { 134 135 // There is a minimum size constraint of 200px by 200px 136 if ($facebookImage->getWidth() < 200) { 137 $toSmall = true; 138 } else { 139 $facebookMeta["og:image:width"] = $facebookImage->getWidth(); 140 if ($facebookImage->getHeight() < 200) { 141 $toSmall = true; 142 } else { 143 $facebookMeta["og:image:height"] = $facebookImage->getHeight(); 144 } 145 } 146 } 147 148 if ($toSmall) { 149 $message = "The facebook image ($facebookImage) is too small (" . $facebookImage->getWidth() . " x " . $facebookImage->getHeight() . "). The minimum size constraint is 200px by 200px"; 150 if ($facebookImage->getId() != $page->getFirstImage()->getId()) { 151 LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 152 } else { 153 LogUtility::log2BrowserConsole($message); 154 } 155 } 156 157 158 /** 159 * We may don't known the dimensions 160 */ 161 if (!$toSmall) { 162 $mime = $facebookImage->getMime(); 163 if (!empty($mime)) { 164 $facebookMeta["og:image:type"] = $mime[1]; 165 } 166 $facebookMeta["og:image"] = $facebookImage->getUrl(); 167 // One image only 168 break; 169 } 170 } 171 172 } 173 } 174 175 176 $facebookMeta["fb:app_id"] = self::FACEBOOK_APP_ID; 177 178 $lang = $page->getLang(); 179 if (!empty($lang)) { 180 181 $country = $page->getCountry(); 182 if (empty($country)) { 183 $country = $lang; 184 } 185 $facebookMeta["og:locale"] = $lang . "_" . strtoupper($country); 186 187 } else { 188 189 // The Facebook default 190 $facebookMeta["og:locale"] = "en_US"; 191 192 } 193 194 /** 195 * Add the properties 196 */ 197 foreach ($facebookMeta as $property => $content) { 198 $event->data['meta'][] = array("property" => $property, "content" => $content); 199 } 200 201 202 } 203 204} 205