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