xref: /plugin/combo/action/metafacebook.php (revision 85e82846b0a214bc35e62864fa49d9cad0723d0e)
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