1<?php
2
3use ComboStrap\BlockquoteTag;
4use ComboStrap\ExceptionBadArgument;
5use ComboStrap\ExceptionBadSyntax;
6use ComboStrap\ExceptionNotExists;
7use ComboStrap\ExecutionContext;
8use ComboStrap\FetcherRaster;
9use ComboStrap\Meta\Field\TwitterImage;
10use ComboStrap\Site;
11use ComboStrap\SiteConfig;
12use ComboStrap\WikiPath;
13use ComboStrap\ExceptionCompile;
14use ComboStrap\ExceptionNotFound;
15use ComboStrap\IFetcherLocalImage;
16use ComboStrap\FileSystems;
17use ComboStrap\LogUtility;
18use ComboStrap\MarkupPath;
19use ComboStrap\PageImageUsage;
20use ComboStrap\PluginUtility;
21use ComboStrap\ResourceName;
22use ComboStrap\StringUtility;
23
24
25require_once(__DIR__ . '/../ComboStrap/Site.php');
26
27/**
28 *
29 * For the canonical meta, see {@link action_plugin_combo_metacanonical}
30 * https://github.com/twbs/bootstrap/blob/v4-dev/site/layouts/partials/social.html
31 *
32 * TODO: https://developer.twitter.com/en/docs/twitter-for-websites/embedded-tweets/overview
33 */
34class action_plugin_combo_metatwitter extends DokuWiki_Action_Plugin
35{
36
37
38    /**
39     * The handle name
40     */
41    const CONF_TWITTER_SITE_HANDLE = "twitterSiteHandle";
42    /**
43     * The handle id
44     */
45    const CONF_TWITTER_SITE_ID = "twitterSiteId";
46
47    /**
48     * Don't track
49     */
50    const CONF_TWITTER_DONT_NOT_TRACK = self::META_DNT;
51    const CONF_DONT_NOT_TRACK = self::META_DNT;
52    const CONF_ON = "on";
53    const CONF_OFF = "off";
54
55    /**
56     * The creation ie (combostrap)
57     */
58    const COMBO_STRAP_TWITTER_HANDLE = "@combostrapweb";
59    const COMBO_STRAP_TWITTER_ID = "1283330969332842497";
60    const CANONICAL = "twitter";
61
62    const META_CARD = "twitter:card";
63    const DEFAULT_IMAGE = ":apple-touch-icon.png";
64    const META_DESCRIPTION = "twitter:description";
65    const META_IMAGE = "twitter:image";
66    const META_TITLE = "twitter:title";
67    const META_CREATOR = "twitter:creator";
68    const META_CREATOR_ID = "twitter:creator:id";
69    const META_SITE = "twitter:site";
70    const META_SITE_ID = "twitter:site:id";
71    const META_IMAGE_ALT = "twitter:image:alt";
72    const META_DNT = "twitter:dnt";
73    const META_WIDGET_CSP = "twitter:widgets:csp";
74    const META_WIDGETS_THEME = "twitter:widgets:theme";
75    const META_WIDGETS_BORDER_COLOR = "twitter:widgets:border-color";
76
77
78    function __construct()
79    {
80        // enable direct access to language strings
81        // ie $this->lang
82        $this->setupLocale();
83    }
84
85    public function register(Doku_Event_Handler $controller)
86    {
87        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaTwitterProcessing', array());
88    }
89
90    /**
91     *
92     * @param $event
93     */
94    function metaTwitterProcessing($event)
95    {
96
97        $executionContext = ExecutionContext::getActualOrCreateFromEnv();
98
99        try {
100            $templateForWebPage = $executionContext->getExecutingPageTemplate();
101            if(!$templateForWebPage->isSocial()){
102                return;
103            }
104            $page = MarkupPath::createPageFromPathObject($templateForWebPage->getRequestedContextPath());
105        } catch (ExceptionNotFound $e) {
106            return;
107        }
108
109
110        if (!FileSystems::exists($page)) {
111            return;
112        }
113
114        /**
115         * No social for bars
116         */
117        if ($page->isSlot()) {
118            return;
119        }
120
121
122        // https://datacadamia.com/marketing/twitter#html_meta
123        // https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup
124        // https://cards-dev.twitter.com/validator
125
126
127        $twitterMeta = array(
128            self::META_CARD => "summary",
129            self::META_TITLE => StringUtility::truncateString($page->getTitleOrDefault(), 70),
130            self::META_CREATOR => self::COMBO_STRAP_TWITTER_HANDLE,
131            self::META_CREATOR_ID => self::COMBO_STRAP_TWITTER_ID
132        );
133        $description = $page->getDescriptionOrElseDokuWiki();
134        if (!empty($description)) {
135            // happens in test with document without content
136            $twitterMeta[self::META_DESCRIPTION] = StringUtility::truncateString($description, 200);
137        }
138
139
140        /**
141         * Twitter site
142         */
143        $siteTwitterHandle = $this->getConf(self::CONF_TWITTER_SITE_HANDLE);
144        $siteTwitterId = $this->getConf(self::CONF_TWITTER_SITE_ID);
145        if (!empty($siteTwitterHandle)) {
146            $twitterMeta[self::META_SITE] = $siteTwitterHandle;
147
148            // Identify the Twitter profile of the page that populates the via property
149            // https://developer.twitter.com/en/docs/twitter-for-websites/webpage-properties
150            $name = str_replace("@", "", $siteTwitterHandle);
151            $event->data['link'][] = array("rel" => "me", "href" => "https://twitter.com/$name");
152        }
153        if (!empty($siteTwitterId)) {
154            $twitterMeta[self::META_SITE_ID] = $siteTwitterId;
155        }
156
157        /**
158         * Card image
159         */
160        try {
161            $twitterImagePath = TwitterImage::createFromResource($page)->getValueOrDefault();
162        } catch (ExceptionNotFound $e) {
163            // no twitter image
164            return;
165        }
166
167        if (!FileSystems::exists($twitterImagePath)) {
168            LogUtility::error("The twitter image ($twitterImagePath) does not exists.", self::CANONICAL);
169            return;
170        }
171
172        try {
173            $twitterMeta[self::META_IMAGE] = FetcherRaster::createImageFetchFromPath($twitterImagePath)->getFetchUrl()->toAbsoluteUrlString();
174        } catch (ExceptionBadArgument|ExceptionBadSyntax|ExceptionNotExists $e) {
175            LogUtility::error("Error with the twitter image url. " . $e->getMessage(), self::CANONICAL, $e);
176            return;
177        }
178
179        $title = ResourceName::getFromPath($twitterImagePath);
180        if (!empty($title)) {
181            $twitterMeta[self::META_IMAGE_ALT] = $title;
182        }
183
184        /**
185         * https://developer.twitter.com/en/docs/twitter-for-websites/webpage-properties
186         */
187        // don't track
188        $twitterMeta[self::META_DNT] = $this->getConf(self::CONF_TWITTER_DONT_NOT_TRACK, self::CONF_ON);
189        // turn off csp warning
190        $twitterMeta[self::META_WIDGET_CSP] = "on";
191
192        /**
193         * Embedded Tweet Theme
194         */
195        $twitterMeta[self::META_WIDGETS_THEME] = $this->getConf(BlockquoteTag::CONF_TWEET_WIDGETS_THEME, BlockquoteTag::CONF_TWEET_WIDGETS_THEME_DEFAULT);
196        $twitterMeta[self::META_WIDGETS_BORDER_COLOR] = $this->getConf(BlockquoteTag::CONF_TWEET_WIDGETS_BORDER, BlockquoteTag::CONF_TWEET_WIDGETS_BORDER_DEFAULT);
197
198        /**
199         * Add the properties
200         */
201        foreach ($twitterMeta as $key => $content) {
202            $event->data['meta'][] = array("name" => $key, "content" => $content);
203        }
204
205
206    }
207
208}
209