14cadd4f8SNickeau<?php 24cadd4f8SNickeau 34cadd4f8SNickeau 44cadd4f8SNickeaunamespace ComboStrap; 54cadd4f8SNickeau 64cadd4f8SNickeau 74cadd4f8SNickeauuse action_plugin_combo_metatwitter; 804fd306cSNickeauuse ComboStrap\TagAttribute\StyleAttribute; 94cadd4f8SNickeau 104cadd4f8SNickeau/** 114cadd4f8SNickeau * 124cadd4f8SNickeau * Brand button 134cadd4f8SNickeau * * basic 144cadd4f8SNickeau * * share 154cadd4f8SNickeau * * follow 164cadd4f8SNickeau * 174cadd4f8SNickeau * @package ComboStrap 184cadd4f8SNickeau * 194cadd4f8SNickeau * 204cadd4f8SNickeau * Share link: 214cadd4f8SNickeau * * [Link](https://github.com/mxstbr/sharingbuttons.io/blob/master/js/stores/AppStore.js#L242) 224cadd4f8SNickeau * * https://github.com/ellisonleao/sharer.js/blob/main/sharer.js#L72 234cadd4f8SNickeau * Style: 244cadd4f8SNickeau * * [Style](https://github.com/mxstbr/sharingbuttons.io/blob/master/js/stores/AppStore.js#L10) 254cadd4f8SNickeau * 264cadd4f8SNickeau * Popup: 274cadd4f8SNickeau * https://gist.github.com/josephabrahams/9d023596b884e80e37e5 284cadd4f8SNickeau * https://jonsuh.com/blog/social-share-links/ 294cadd4f8SNickeau * https://stackoverflow.com/questions/11473345/how-to-pop-up-new-window-with-tweet-button 304cadd4f8SNickeau * 314cadd4f8SNickeau * Inspired by: 324cadd4f8SNickeau * http://sharingbuttons.io (Specifically thanks for the data) 334cadd4f8SNickeau */ 344cadd4f8SNickeauclass BrandButton 354cadd4f8SNickeau{ 364cadd4f8SNickeau public const WIDGET_BUTTON_VALUE = "button"; 374cadd4f8SNickeau public const WIDGET_LINK_VALUE = "link"; 384cadd4f8SNickeau const WIDGETS = [self::WIDGET_BUTTON_VALUE, self::WIDGET_LINK_VALUE]; 394cadd4f8SNickeau const ICON_SOLID_VALUE = "solid"; 404cadd4f8SNickeau const ICON_SOLID_CIRCLE_VALUE = "solid-circle"; 414cadd4f8SNickeau const ICON_OUTLINE_CIRCLE_VALUE = "outline-circle"; 424cadd4f8SNickeau const ICON_OUTLINE_VALUE = "outline"; 434cadd4f8SNickeau const ICON_TYPES = [self::ICON_SOLID_VALUE, self::ICON_SOLID_CIRCLE_VALUE, self::ICON_OUTLINE_VALUE, self::ICON_OUTLINE_CIRCLE_VALUE, self::ICON_NONE_VALUE]; 444cadd4f8SNickeau const ICON_NONE_VALUE = "none"; 454cadd4f8SNickeau 464cadd4f8SNickeau const CANONICAL = "social"; 474cadd4f8SNickeau 484cadd4f8SNickeau 494cadd4f8SNickeau /** 504cadd4f8SNickeau * @var string 514cadd4f8SNickeau */ 524cadd4f8SNickeau private $widget = self::WIDGET_BUTTON_VALUE; 534cadd4f8SNickeau /** 544cadd4f8SNickeau * @var mixed|string 554cadd4f8SNickeau */ 564cadd4f8SNickeau private $iconType = self::ICON_SOLID_VALUE; 574cadd4f8SNickeau /** 584cadd4f8SNickeau * The width of the icon 594cadd4f8SNickeau * @var int|null 604cadd4f8SNickeau */ 614cadd4f8SNickeau private $width = null; 624cadd4f8SNickeau /** 634cadd4f8SNickeau * @var string 644cadd4f8SNickeau */ 654cadd4f8SNickeau private $type; 664cadd4f8SNickeau const TYPE_BUTTON_SHARE = "share"; 674cadd4f8SNickeau const TYPE_BUTTON_FOLLOW = "follow"; 684cadd4f8SNickeau const TYPE_BUTTON_BRAND = "brand"; 694cadd4f8SNickeau const TYPE_BUTTONS = [self::TYPE_BUTTON_SHARE, self::TYPE_BUTTON_FOLLOW, self::TYPE_BUTTON_BRAND]; 704cadd4f8SNickeau 714cadd4f8SNickeau 724cadd4f8SNickeau /** 734cadd4f8SNickeau * @var string the follow handle 744cadd4f8SNickeau */ 754cadd4f8SNickeau private $handle; 764cadd4f8SNickeau 774cadd4f8SNickeau 784cadd4f8SNickeau /** 794cadd4f8SNickeau * @var Brand 804cadd4f8SNickeau */ 814cadd4f8SNickeau private $brand; 824cadd4f8SNickeau private $primaryColor; 834cadd4f8SNickeau private $title; 844cadd4f8SNickeau private $secondaryColor; 854cadd4f8SNickeau 864cadd4f8SNickeau 874cadd4f8SNickeau /** 8804fd306cSNickeau * @throws ExceptionCompile 894cadd4f8SNickeau */ 9004fd306cSNickeau public function __construct(string $brandName, string $typeButton) 914cadd4f8SNickeau { 924cadd4f8SNickeau 934cadd4f8SNickeau $this->brand = Brand::create($brandName); 944cadd4f8SNickeau 954cadd4f8SNickeau $this->type = strtolower($typeButton); 964cadd4f8SNickeau if (!in_array($this->type, self::TYPE_BUTTONS)) { 9704fd306cSNickeau throw new ExceptionCompile("The button type ($this->type} is unknown."); 984cadd4f8SNickeau } 994cadd4f8SNickeau 1004cadd4f8SNickeau 1014cadd4f8SNickeau } 1024cadd4f8SNickeau 1034cadd4f8SNickeau /** 1044cadd4f8SNickeau * Return all combination of widget type and icon type 1054cadd4f8SNickeau * @return array 1064cadd4f8SNickeau */ 1074cadd4f8SNickeau public static function getVariants(): array 1084cadd4f8SNickeau { 1094cadd4f8SNickeau $variants = []; 1104cadd4f8SNickeau foreach (self::WIDGETS as $widget) { 1114cadd4f8SNickeau foreach (self::ICON_TYPES as $typeIcon) { 1124cadd4f8SNickeau if ($typeIcon === self::ICON_NONE_VALUE) { 1134cadd4f8SNickeau continue; 1144cadd4f8SNickeau } 11504fd306cSNickeau $variants[] = [BrandTag::ICON_ATTRIBUTE => $typeIcon, TagAttributes::TYPE_KEY => $widget]; 1164cadd4f8SNickeau } 1174cadd4f8SNickeau } 1184cadd4f8SNickeau return $variants; 1194cadd4f8SNickeau } 1204cadd4f8SNickeau 1214cadd4f8SNickeau /** 12204fd306cSNickeau * @throws ExceptionCompile 1234cadd4f8SNickeau */ 1244cadd4f8SNickeau public static function createBrandButton(string $brand): BrandButton 1254cadd4f8SNickeau { 1264cadd4f8SNickeau return new BrandButton($brand, self::TYPE_BUTTON_BRAND); 1274cadd4f8SNickeau } 1284cadd4f8SNickeau 1294cadd4f8SNickeau 1304cadd4f8SNickeau /** 13104fd306cSNickeau * @throws ExceptionCompile 1324cadd4f8SNickeau */ 1334cadd4f8SNickeau public function setWidget($widget): BrandButton 1344cadd4f8SNickeau { 1354cadd4f8SNickeau /** 1364cadd4f8SNickeau * Widget validation 1374cadd4f8SNickeau */ 1384cadd4f8SNickeau $this->widget = $widget; 1394cadd4f8SNickeau $widget = trim(strtolower($widget)); 1404cadd4f8SNickeau if (!in_array($widget, self::WIDGETS)) { 14104fd306cSNickeau throw new ExceptionCompile("The {$this->type} widget ($widget} is unknown. The possible widgets value are " . implode(",", self::WIDGETS)); 1424cadd4f8SNickeau } 1434cadd4f8SNickeau return $this; 1444cadd4f8SNickeau } 1454cadd4f8SNickeau 1464cadd4f8SNickeau /** 14704fd306cSNickeau * @throws ExceptionCompile 1484cadd4f8SNickeau */ 1494cadd4f8SNickeau public function setIconType($iconType): BrandButton 1504cadd4f8SNickeau { 1514cadd4f8SNickeau /** 1524cadd4f8SNickeau * Icon Validation 1534cadd4f8SNickeau */ 1544cadd4f8SNickeau $this->iconType = $iconType; 1554cadd4f8SNickeau $iconType = trim(strtolower($iconType)); 1564cadd4f8SNickeau if (!in_array($iconType, self::ICON_TYPES)) { 15704fd306cSNickeau throw new ExceptionCompile("The icon type ($iconType) is unknown. The possible icons value are " . implode(",", self::ICON_TYPES)); 1584cadd4f8SNickeau } 1594cadd4f8SNickeau return $this; 1604cadd4f8SNickeau } 1614cadd4f8SNickeau 1624cadd4f8SNickeau public function setWidth(?int $width): BrandButton 1634cadd4f8SNickeau { 1644cadd4f8SNickeau /** 1654cadd4f8SNickeau * Width 1664cadd4f8SNickeau */ 1674cadd4f8SNickeau if ($width === null) { 1684cadd4f8SNickeau return $this; 1694cadd4f8SNickeau } 1704cadd4f8SNickeau $this->width = $width; 1714cadd4f8SNickeau return $this; 1724cadd4f8SNickeau } 1734cadd4f8SNickeau 1744cadd4f8SNickeau /** 17504fd306cSNickeau * @throws ExceptionCompile 1764cadd4f8SNickeau */ 1774cadd4f8SNickeau public static function createShareButton( 1784cadd4f8SNickeau string $brandName, 1794cadd4f8SNickeau string $widget = self::WIDGET_BUTTON_VALUE, 1804cadd4f8SNickeau string $icon = self::ICON_SOLID_VALUE, 1814cadd4f8SNickeau ?int $width = null): BrandButton 1824cadd4f8SNickeau { 1834cadd4f8SNickeau return (new BrandButton($brandName, self::TYPE_BUTTON_SHARE)) 1844cadd4f8SNickeau ->setWidget($widget) 1854cadd4f8SNickeau ->setIconType($icon) 1864cadd4f8SNickeau ->setWidth($width); 1874cadd4f8SNickeau } 1884cadd4f8SNickeau 1894cadd4f8SNickeau /** 19004fd306cSNickeau * @throws ExceptionCompile 1914cadd4f8SNickeau */ 1924cadd4f8SNickeau public static function createFollowButton( 1934cadd4f8SNickeau string $brandName, 1944cadd4f8SNickeau string $handle = null, 1954cadd4f8SNickeau string $widget = self::WIDGET_BUTTON_VALUE, 1964cadd4f8SNickeau string $icon = self::ICON_SOLID_VALUE, 1974cadd4f8SNickeau ?int $width = null): BrandButton 1984cadd4f8SNickeau { 1994cadd4f8SNickeau return (new BrandButton($brandName, self::TYPE_BUTTON_FOLLOW)) 2004cadd4f8SNickeau ->setHandle($handle) 2014cadd4f8SNickeau ->setWidget($widget) 2024cadd4f8SNickeau ->setIconType($icon) 2034cadd4f8SNickeau ->setWidth($width); 2044cadd4f8SNickeau } 2054cadd4f8SNickeau 2064cadd4f8SNickeau /** 20704fd306cSNickeau * 2084cadd4f8SNickeau * 2094cadd4f8SNickeau * Dictionary has been made with the data found here: 2104cadd4f8SNickeau * * https://github.com/ellisonleao/sharer.js/blob/main/sharer.js#L72 2114cadd4f8SNickeau * * and 21204fd306cSNickeau * @throws ExceptionBadArgument 2134cadd4f8SNickeau */ 21404fd306cSNickeau public function getBrandEndpointForPage(MarkupPath $requestedPage = null): ?string 2154cadd4f8SNickeau { 2164cadd4f8SNickeau 2174cadd4f8SNickeau /** 2184cadd4f8SNickeau * Shared/Follow Url template 2194cadd4f8SNickeau */ 2204cadd4f8SNickeau $urlTemplate = $this->brand->getWebUrlTemplate($this->type); 2214cadd4f8SNickeau if ($urlTemplate === null) { 22204fd306cSNickeau throw new ExceptionBadArgument("The brand ($this) does not support the $this->type button (The $this->type URL is unknown)"); 2234cadd4f8SNickeau } 2244cadd4f8SNickeau switch ($this->type) { 2254cadd4f8SNickeau 2264cadd4f8SNickeau case self::TYPE_BUTTON_SHARE: 2274cadd4f8SNickeau if ($requestedPage === null) { 22804fd306cSNickeau throw new ExceptionBadArgument("The page requested should not be null for a share button when requesting the endpoint uri."); 2294cadd4f8SNickeau } 2304cadd4f8SNickeau $canonicalUrl = $this->getSharedUrlForPage($requestedPage); 2314cadd4f8SNickeau $templateData["url"] = $canonicalUrl; 2324cadd4f8SNickeau $templateData["title"] = $requestedPage->getTitleOrDefault(); 23304fd306cSNickeau 23404fd306cSNickeau try { 23504fd306cSNickeau $templateData["description"] = $requestedPage->getDescription(); 23604fd306cSNickeau } catch (ExceptionNotFound $e) { 23704fd306cSNickeau $templateData["description"] = ""; 2384cadd4f8SNickeau } 23904fd306cSNickeau 2404cadd4f8SNickeau $templateData["text"] = $this->getTextForPage($requestedPage); 24104fd306cSNickeau 2424cadd4f8SNickeau $via = null; 24304fd306cSNickeau if ($this->brand->getName() == \action_plugin_combo_metatwitter::CANONICAL) { 2444cadd4f8SNickeau $via = substr(action_plugin_combo_metatwitter::COMBO_STRAP_TWITTER_HANDLE, 1); 2454cadd4f8SNickeau } 2464cadd4f8SNickeau if ($via !== null && $via !== "") { 2474cadd4f8SNickeau $templateData["via"] = $via; 2484cadd4f8SNickeau } 2494cadd4f8SNickeau foreach ($templateData as $key => $value) { 2504cadd4f8SNickeau $templateData[$key] = urlencode($value); 2514cadd4f8SNickeau } 2524cadd4f8SNickeau 25304fd306cSNickeau return Template::create($urlTemplate)->setProperties($templateData)->render(); 2544cadd4f8SNickeau 2554cadd4f8SNickeau case self::TYPE_BUTTON_FOLLOW: 2564cadd4f8SNickeau if ($this->handle === null) { 2574cadd4f8SNickeau return $urlTemplate; 2584cadd4f8SNickeau } 25904fd306cSNickeau $templateData[Tag\FollowTag::HANDLE_ATTRIBUTE] = $this->handle; 26004fd306cSNickeau return Template::create($urlTemplate)->setProperties($templateData)->render(); 2614cadd4f8SNickeau default: 2624cadd4f8SNickeau // The type is mandatory and checked at creation, 2634cadd4f8SNickeau // it should not happen, we don't throw an error 2644cadd4f8SNickeau $message = "Button type ($this->type) is unknown"; 2654cadd4f8SNickeau LogUtility::msg($message, LogUtility::LVL_MSG_ERROR, self::CANONICAL); 2664cadd4f8SNickeau return $message; 2674cadd4f8SNickeau } 2684cadd4f8SNickeau 2694cadd4f8SNickeau } 2704cadd4f8SNickeau 2714cadd4f8SNickeau public function __toString() 2724cadd4f8SNickeau { 2734cadd4f8SNickeau return $this->brand->__toString(); 2744cadd4f8SNickeau } 2754cadd4f8SNickeau 27604fd306cSNickeau public function getLabel(): string 2774cadd4f8SNickeau { 2784cadd4f8SNickeau $title = $this->title; 2794cadd4f8SNickeau if ($title !== null && trim($title) !== "") { 2804cadd4f8SNickeau return $title; 2814cadd4f8SNickeau } 2824cadd4f8SNickeau $title = $this->brand->getTitle($this->iconType); 2834cadd4f8SNickeau if ($title !== null && trim($title) !== "") { 2844cadd4f8SNickeau return $title; 2854cadd4f8SNickeau } 2864cadd4f8SNickeau $name = ucfirst($this->brand->getName()); 2874cadd4f8SNickeau switch ($this->type) { 2884cadd4f8SNickeau case self::TYPE_BUTTON_SHARE: 2894cadd4f8SNickeau return "Share this page via $name"; 2904cadd4f8SNickeau case self::TYPE_BUTTON_FOLLOW: 2914cadd4f8SNickeau return "Follow us on $name"; 2924cadd4f8SNickeau case self::TYPE_BUTTON_BRAND: 2934cadd4f8SNickeau return $name; 2944cadd4f8SNickeau default: 2954cadd4f8SNickeau return "Button type ($this->type) is unknown"; 2964cadd4f8SNickeau } 2974cadd4f8SNickeau } 2984cadd4f8SNickeau 2994cadd4f8SNickeau /** 30004fd306cSNickeau * @throws ExceptionCompile 3014cadd4f8SNickeau */ 3024cadd4f8SNickeau public 3034cadd4f8SNickeau function getStyle(): string 3044cadd4f8SNickeau { 3054cadd4f8SNickeau 3064cadd4f8SNickeau /** 3074cadd4f8SNickeau * Default colors 3084cadd4f8SNickeau */ 3094cadd4f8SNickeau // make the button/link space square 3104cadd4f8SNickeau $properties["padding"] = "0.375rem 0.375rem"; 3114cadd4f8SNickeau switch ($this->widget) { 3124cadd4f8SNickeau case self::WIDGET_LINK_VALUE: 3134cadd4f8SNickeau $properties["vertical-align"] = "middle"; 3144cadd4f8SNickeau $properties["display"] = "inline-block"; 3154cadd4f8SNickeau $primaryColor = $this->getPrimaryColor(); 3164cadd4f8SNickeau if ($primaryColor !== null) { 3174cadd4f8SNickeau // important because the nav-bar class takes over 3184cadd4f8SNickeau $properties["color"] = "$primaryColor!important"; 3194cadd4f8SNickeau } 3204cadd4f8SNickeau break; 3214cadd4f8SNickeau default: 3224cadd4f8SNickeau case self::WIDGET_BUTTON_VALUE: 3234cadd4f8SNickeau 3244cadd4f8SNickeau $primary = $this->getPrimaryColor(); 3254cadd4f8SNickeau if ($primary === null) { 3264cadd4f8SNickeau // custom brand default color 3274cadd4f8SNickeau $primary = ComboStrap::PRIMARY_COLOR; 3284cadd4f8SNickeau } 3294cadd4f8SNickeau $textColor = $this->getTextColor(); 3304cadd4f8SNickeau if ($textColor === null || $textColor === "") { 3314cadd4f8SNickeau $textColor = "#fff"; 3324cadd4f8SNickeau } 3334cadd4f8SNickeau $properties["background-color"] = $primary; 3344cadd4f8SNickeau $properties["border-color"] = $primary; 3354cadd4f8SNickeau $properties["color"] = $textColor; 3364cadd4f8SNickeau break; 3374cadd4f8SNickeau } 3384cadd4f8SNickeau switch ($this->iconType) { 3394cadd4f8SNickeau case self::ICON_OUTLINE_VALUE: 3404cadd4f8SNickeau // not for outline circle, it's cut otherwise, don't know why 3414cadd4f8SNickeau $properties["stroke-width"] = "2px"; 3424cadd4f8SNickeau break; 3434cadd4f8SNickeau } 3444cadd4f8SNickeau 3454cadd4f8SNickeau $cssProperties = "\n"; 3464cadd4f8SNickeau foreach ($properties as $key => $value) { 3474cadd4f8SNickeau $cssProperties .= " $key:$value;\n"; 3484cadd4f8SNickeau } 3494cadd4f8SNickeau $style = <<<EOF 3504cadd4f8SNickeau.{$this->getIdentifierClass()} {{$cssProperties}} 3514cadd4f8SNickeauEOF; 3524cadd4f8SNickeau 3534cadd4f8SNickeau /** 3544cadd4f8SNickeau * Hover Style 3554cadd4f8SNickeau */ 3564cadd4f8SNickeau $secondary = $this->getSecondaryColor(); 3574cadd4f8SNickeau if ($secondary === null) { 3584cadd4f8SNickeau return $style; 3594cadd4f8SNickeau } 3604cadd4f8SNickeau $hoverProperties = []; 3614cadd4f8SNickeau switch ($this->widget) { 3624cadd4f8SNickeau case self::WIDGET_LINK_VALUE: 3634cadd4f8SNickeau $hoverProperties["color"] = $secondary; 3644cadd4f8SNickeau break; 3654cadd4f8SNickeau default: 3664cadd4f8SNickeau case self::WIDGET_BUTTON_VALUE: 3674cadd4f8SNickeau $textColor = $this->getTextColor(); 3684cadd4f8SNickeau $hoverProperties["background-color"] = $secondary; 3694cadd4f8SNickeau $hoverProperties["border-color"] = $secondary; 3704cadd4f8SNickeau $hoverProperties["color"] = $textColor; 3714cadd4f8SNickeau break; 3724cadd4f8SNickeau } 3734cadd4f8SNickeau $hoverCssProperties = "\n"; 3744cadd4f8SNickeau foreach ($hoverProperties as $key => $value) { 3754cadd4f8SNickeau $hoverCssProperties .= " $key:$value;\n"; 3764cadd4f8SNickeau } 3774cadd4f8SNickeau $hoverStyle = <<<EOF 3784cadd4f8SNickeau.{$this->getIdentifierClass()}:hover, .{$this->getIdentifierClass()}:active {{$hoverCssProperties}} 3794cadd4f8SNickeauEOF; 3804cadd4f8SNickeau 3814cadd4f8SNickeau return <<<EOF 3824cadd4f8SNickeau$style 3834cadd4f8SNickeau$hoverStyle 3844cadd4f8SNickeauEOF; 3854cadd4f8SNickeau 3864cadd4f8SNickeau 3874cadd4f8SNickeau } 3884cadd4f8SNickeau 3894cadd4f8SNickeau public function getBrand(): Brand 3904cadd4f8SNickeau { 3914cadd4f8SNickeau return $this->brand; 3924cadd4f8SNickeau } 3934cadd4f8SNickeau 3944cadd4f8SNickeau /** 3954cadd4f8SNickeau * The identifier of the {@link BrandButton::getStyle()} script 39604fd306cSNickeau * used as script id in the {@link SnippetSystem} 3974cadd4f8SNickeau * @return string 3984cadd4f8SNickeau */ 3994cadd4f8SNickeau public 4004cadd4f8SNickeau function getStyleScriptIdentifier(): string 4014cadd4f8SNickeau { 4024cadd4f8SNickeau return "{$this->getType()}-{$this->brand->getName()}-{$this->getWidget()}-{$this->getIcon()}"; 4034cadd4f8SNickeau } 4044cadd4f8SNickeau 4054cadd4f8SNickeau /** 4064cadd4f8SNickeau * @return string - the class identifier used in the {@link BrandButton::getStyle()} script 4074cadd4f8SNickeau */ 4084cadd4f8SNickeau public 4094cadd4f8SNickeau function getIdentifierClass(): string 4104cadd4f8SNickeau { 41104fd306cSNickeau return StyleAttribute::addComboStrapSuffix($this->getStyleScriptIdentifier()); 4124cadd4f8SNickeau } 4134cadd4f8SNickeau 4144cadd4f8SNickeau /** 41504fd306cSNickeau * @throws ExceptionNotFound 4164cadd4f8SNickeau */ 4174cadd4f8SNickeau public 4184cadd4f8SNickeau function getIconAttributes(): array 4194cadd4f8SNickeau { 4204cadd4f8SNickeau 4214cadd4f8SNickeau $iconName = $this->getResourceIconName(); 4224cadd4f8SNickeau $icon = $this->getResourceIconFile(); 4234cadd4f8SNickeau if (!FileSystems::exists($icon)) { 4244cadd4f8SNickeau $iconName = $this->brand->getIconName($this->iconType); 4254cadd4f8SNickeau $brandNames = Brand::getAllKnownBrandNames(); 4264cadd4f8SNickeau if ($iconName === null && in_array($this->getBrand(), $brandNames)) { 42704fd306cSNickeau throw new ExceptionNotFound("No {$this->iconType} icon could be found for the known brand ($this)"); 4284cadd4f8SNickeau } 4294cadd4f8SNickeau } 43004fd306cSNickeau $attributes = [FetcherSvg::NAME_ATTRIBUTE => $iconName]; 4314cadd4f8SNickeau $textColor = $this->getTextColor(); 4324cadd4f8SNickeau if ($textColor !== null) { 4334cadd4f8SNickeau $attributes[ColorRgb::COLOR] = $textColor; 4344cadd4f8SNickeau } 4354cadd4f8SNickeau $attributes[Dimension::WIDTH_KEY] = $this->getWidth(); 4364cadd4f8SNickeau 4374cadd4f8SNickeau return $attributes; 4384cadd4f8SNickeau } 4394cadd4f8SNickeau 4404cadd4f8SNickeau public 4414cadd4f8SNickeau function getTextColor(): ?string 4424cadd4f8SNickeau { 4434cadd4f8SNickeau 4444cadd4f8SNickeau switch ($this->widget) { 4454cadd4f8SNickeau case self::WIDGET_LINK_VALUE: 4464cadd4f8SNickeau return $this->getPrimaryColor(); 4474cadd4f8SNickeau default: 4484cadd4f8SNickeau case self::WIDGET_BUTTON_VALUE: 4494cadd4f8SNickeau return "#fff"; 4504cadd4f8SNickeau } 4514cadd4f8SNickeau 4524cadd4f8SNickeau } 4534cadd4f8SNickeau 4544cadd4f8SNickeau /** 4554cadd4f8SNickeau * Class added to the link 4564cadd4f8SNickeau * This is just to be boostrap conformance 4574cadd4f8SNickeau */ 4584cadd4f8SNickeau public 4594cadd4f8SNickeau function getWidgetClass(): string 4604cadd4f8SNickeau { 46104fd306cSNickeau /** 46204fd306cSNickeau * The btn bootstrap class: 46304fd306cSNickeau * * makes a link a button 46404fd306cSNickeau * * and normalize the button styling 46504fd306cSNickeau */ 4664cadd4f8SNickeau return "btn"; 4674cadd4f8SNickeau } 4684cadd4f8SNickeau 4694cadd4f8SNickeau 4704cadd4f8SNickeau public 4714cadd4f8SNickeau function getWidget(): string 4724cadd4f8SNickeau { 4734cadd4f8SNickeau return $this->widget; 4744cadd4f8SNickeau } 4754cadd4f8SNickeau 4764cadd4f8SNickeau private 4774cadd4f8SNickeau function getIcon() 4784cadd4f8SNickeau { 4794cadd4f8SNickeau return $this->iconType; 4804cadd4f8SNickeau } 4814cadd4f8SNickeau 4824cadd4f8SNickeau private 4834cadd4f8SNickeau function getDefaultWidth(): int 4844cadd4f8SNickeau { 4854cadd4f8SNickeau switch ($this->widget) { 4864cadd4f8SNickeau case self::WIDGET_LINK_VALUE: 4874cadd4f8SNickeau return 36; 4884cadd4f8SNickeau case self::WIDGET_BUTTON_VALUE: 4894cadd4f8SNickeau default: 4904cadd4f8SNickeau return 24; 4914cadd4f8SNickeau } 4924cadd4f8SNickeau } 4934cadd4f8SNickeau 4944cadd4f8SNickeau private 4954cadd4f8SNickeau function getWidth(): ?int 4964cadd4f8SNickeau { 4974cadd4f8SNickeau if ($this->width === null) { 4984cadd4f8SNickeau return $this->getDefaultWidth(); 4994cadd4f8SNickeau } 5004cadd4f8SNickeau return $this->width; 5014cadd4f8SNickeau } 5024cadd4f8SNickeau 5034cadd4f8SNickeau public function hasIcon(): bool 5044cadd4f8SNickeau { 5054cadd4f8SNickeau if ($this->iconType === self::ICON_NONE_VALUE) { 5064cadd4f8SNickeau return false; 5074cadd4f8SNickeau } 50804fd306cSNickeau 5094cadd4f8SNickeau if ($this->brand->getIconName($this->iconType) !== null) { 5104cadd4f8SNickeau return true; 5114cadd4f8SNickeau } 51204fd306cSNickeau 5134cadd4f8SNickeau if (!FileSystems::exists($this->getResourceIconFile())) { 5144cadd4f8SNickeau return false; 5154cadd4f8SNickeau } 5164cadd4f8SNickeau return true; 5174cadd4f8SNickeau } 5184cadd4f8SNickeau 51904fd306cSNickeau 52004fd306cSNickeau /** 52104fd306cSNickeau */ 5224cadd4f8SNickeau public 52304fd306cSNickeau function getTextForPage(MarkupPath $requestedPage): string 5244cadd4f8SNickeau { 52504fd306cSNickeau 52604fd306cSNickeau try { 52704fd306cSNickeau return "{$requestedPage->getTitleOrDefault()} > {$requestedPage->getDescription()}"; 52804fd306cSNickeau } catch (ExceptionNotFound $e) { 52904fd306cSNickeau // no description, may be ? 53004fd306cSNickeau return $requestedPage->getTitleOrDefault(); 5314cadd4f8SNickeau } 5324cadd4f8SNickeau 5334cadd4f8SNickeau } 5344cadd4f8SNickeau 5354cadd4f8SNickeau public 53604fd306cSNickeau function getSharedUrlForPage(MarkupPath $requestedPage): string 5374cadd4f8SNickeau { 53804fd306cSNickeau return $requestedPage->getCanonicalUrl()->toAbsoluteUrlString(); 5394cadd4f8SNickeau } 5404cadd4f8SNickeau 5414cadd4f8SNickeau /** 54204fd306cSNickeau * Return the button HTML attributes 54304fd306cSNickeau * @throws ExceptionCompile 5444cadd4f8SNickeau */ 5454cadd4f8SNickeau public 54604fd306cSNickeau function getHtmlAttributes(MarkupPath $requestedPage = null): TagAttributes 5474cadd4f8SNickeau { 5484cadd4f8SNickeau 5494cadd4f8SNickeau 5504cadd4f8SNickeau $logicalTag = $this->type; 55104fd306cSNickeau $buttonAttributes = TagAttributes::createEmpty($logicalTag); 55204fd306cSNickeau $buttonAttributes->addComponentAttributeValue(TagAttributes::TYPE_KEY, $logicalTag); 55304fd306cSNickeau $buttonAttributes->addClassName("{$this->getWidgetClass()} {$this->getIdentifierClass()}"); 55404fd306cSNickeau $label = $this->getLabel(); 5554cadd4f8SNickeau switch ($this->type) { 5564cadd4f8SNickeau case self::TYPE_BUTTON_SHARE: 5574cadd4f8SNickeau 5584cadd4f8SNickeau if ($requestedPage === null) { 55904fd306cSNickeau throw new ExceptionCompile("The page requested should not be null for a share button"); 5604cadd4f8SNickeau } 5614cadd4f8SNickeau 5624cadd4f8SNickeau switch ($this->getBrand()) { 5634cadd4f8SNickeau case "whatsapp": 5644cadd4f8SNickeau /** 5654cadd4f8SNickeau * Direct link 5664cadd4f8SNickeau * For whatsapp, the sharer link is not the good one 5674cadd4f8SNickeau */ 56804fd306cSNickeau $buttonAttributes->addOutputAttributeValue("target", "_blank"); 56904fd306cSNickeau $buttonAttributes->addOutputAttributeValue("href", $this->getBrandEndpointForPage($requestedPage)); 570*8b8569b7Sgerardnico $buttonAttributes->addOutputAttributeValue("title", $label); 5714cadd4f8SNickeau break; 5724cadd4f8SNickeau default: 5734cadd4f8SNickeau /** 5744cadd4f8SNickeau * Sharer 5754cadd4f8SNickeau * https://ellisonleao.github.io/sharer.js/ 5764cadd4f8SNickeau */ 5774cadd4f8SNickeau /** 5784cadd4f8SNickeau * Opens in a popup 5794cadd4f8SNickeau */ 58004fd306cSNickeau $buttonAttributes->addOutputAttributeValue("rel", "noopener"); 5814cadd4f8SNickeau 58204fd306cSNickeau PluginUtility::getSnippetManager()->attachRemoteJavascriptLibrary( 5834cadd4f8SNickeau "sharer", 5844cadd4f8SNickeau "https://cdn.jsdelivr.net/npm/sharer.js@0.5.0/sharer.min.js", 5854cadd4f8SNickeau "sha256-AqqY/JJCWPQwZFY/mAhlvxjC5/880Q331aOmargQVLU=" 5864cadd4f8SNickeau ); 58704fd306cSNickeau $buttonAttributes->addOutputAttributeValue("aria-label", $label); 58804fd306cSNickeau $buttonAttributes->addOutputAttributeValue("data-sharer", $this->getBrand()); // the id 58904fd306cSNickeau $buttonAttributes->addOutputAttributeValue("data-link", "false"); 59004fd306cSNickeau $buttonAttributes->addOutputAttributeValue("data-title", $this->getTextForPage($requestedPage)); 5914cadd4f8SNickeau $urlToShare = $this->getSharedUrlForPage($requestedPage); 59204fd306cSNickeau $buttonAttributes->addOutputAttributeValue("data-url", $urlToShare); 5934cadd4f8SNickeau //$linkAttributes->addComponentAttributeValue("href", "#"); // with # we style navigate to the top 59404fd306cSNickeau $buttonAttributes->addStyleDeclarationIfNotSet("cursor", "pointer"); // show a pointer (without href, there is none) 5954cadd4f8SNickeau } 59604fd306cSNickeau return $buttonAttributes; 5974cadd4f8SNickeau case self::TYPE_BUTTON_FOLLOW: 5984cadd4f8SNickeau 59904fd306cSNickeau $buttonAttributes->addOutputAttributeValue("title", $label); 60004fd306cSNickeau $buttonAttributes->addOutputAttributeValue("target", "_blank"); 60104fd306cSNickeau $buttonAttributes->addOutputAttributeValue("rel", "nofollow"); 6024cadd4f8SNickeau $href = $this->getBrandEndpointForPage(); 6034cadd4f8SNickeau if ($href !== null) { 60404fd306cSNickeau $buttonAttributes->addOutputAttributeValue("href", $href); 6054cadd4f8SNickeau } 60604fd306cSNickeau return $buttonAttributes; 6074cadd4f8SNickeau case self::TYPE_BUTTON_BRAND: 6084cadd4f8SNickeau if ($this->brand->getBrandUrl() !== null) { 60904fd306cSNickeau $buttonAttributes->addOutputAttributeValue("href", $this->brand->getBrandUrl()); 6104cadd4f8SNickeau } 61104fd306cSNickeau $buttonAttributes->addOutputAttributeValue("title", $label); 61204fd306cSNickeau return $buttonAttributes; 6134cadd4f8SNickeau default: 61404fd306cSNickeau return $buttonAttributes; 6154cadd4f8SNickeau 6164cadd4f8SNickeau } 6174cadd4f8SNickeau 6184cadd4f8SNickeau 6194cadd4f8SNickeau } 6204cadd4f8SNickeau 6214cadd4f8SNickeau 62204fd306cSNickeau public 6234cadd4f8SNickeau function getType(): string 6244cadd4f8SNickeau { 6254cadd4f8SNickeau return $this->type; 6264cadd4f8SNickeau } 6274cadd4f8SNickeau 6284cadd4f8SNickeau public function setHandle(string $handle): BrandButton 6294cadd4f8SNickeau { 6304cadd4f8SNickeau $this->handle = $handle; 6314cadd4f8SNickeau return $this; 6324cadd4f8SNickeau } 6334cadd4f8SNickeau 6344cadd4f8SNickeau public function setLinkTitle(string $title): BrandButton 6354cadd4f8SNickeau { 6364cadd4f8SNickeau $this->title = $title; 6374cadd4f8SNickeau return $this; 6384cadd4f8SNickeau } 6394cadd4f8SNickeau 6404cadd4f8SNickeau public function setPrimaryColor(string $color): BrandButton 6414cadd4f8SNickeau { 6424cadd4f8SNickeau $this->primaryColor = $color; 6434cadd4f8SNickeau return $this; 6444cadd4f8SNickeau } 6454cadd4f8SNickeau 64604fd306cSNickeau private function getResourceIconFile(): WikiPath 6474cadd4f8SNickeau { 6484cadd4f8SNickeau $iconName = $this->getResourceIconName(); 64904fd306cSNickeau $iconPath = str_replace(IconDownloader::COMBO, "", $iconName) . ".svg"; 65004fd306cSNickeau return WikiPath::createComboResource($iconPath); 6514cadd4f8SNickeau } 6524cadd4f8SNickeau 6534cadd4f8SNickeau public function setSecondaryColor(string $secondaryColor): BrandButton 6544cadd4f8SNickeau { 6554cadd4f8SNickeau $this->secondaryColor = $secondaryColor; 6564cadd4f8SNickeau return $this; 6574cadd4f8SNickeau } 6584cadd4f8SNickeau 6594cadd4f8SNickeau private function getResourceIconName(): string 6604cadd4f8SNickeau { 66104fd306cSNickeau $comboLibrary = IconDownloader::COMBO; 66204fd306cSNickeau return "$comboLibrary:brand:{$this->getBrand()->getName()}:{$this->iconType}"; 6634cadd4f8SNickeau } 6644cadd4f8SNickeau 6654cadd4f8SNickeau 6664cadd4f8SNickeau private function getPrimaryColor(): ?string 6674cadd4f8SNickeau { 6684cadd4f8SNickeau if ($this->primaryColor !== null) { 6694cadd4f8SNickeau return $this->primaryColor; 6704cadd4f8SNickeau } 6714cadd4f8SNickeau return $this->brand->getPrimaryColor(); 6724cadd4f8SNickeau } 6734cadd4f8SNickeau 6744cadd4f8SNickeau private function getSecondaryColor(): ?string 6754cadd4f8SNickeau { 6764cadd4f8SNickeau if ($this->secondaryColor !== null) { 6774cadd4f8SNickeau return $this->secondaryColor; 6784cadd4f8SNickeau } 6794cadd4f8SNickeau return $this->brand->getSecondaryColor(); 6804cadd4f8SNickeau } 6814cadd4f8SNickeau 68204fd306cSNickeau /** 68304fd306cSNickeau * The button is sometimes: 68404fd306cSNickeau * * a HTML button 68504fd306cSNickeau * * and other times a HTML link 68604fd306cSNickeau * 68704fd306cSNickeau * It seems that the button is mostly for data-sharer (share button) 68804fd306cSNickeau * 68904fd306cSNickeau * A Link should have an href otherwise the SEO scan will not be happy 69004fd306cSNickeau * A button should have a aria-label 69104fd306cSNickeau * 69204fd306cSNickeau * @param $tagAttributes 69304fd306cSNickeau * @return string 69404fd306cSNickeau */ 69504fd306cSNickeau public function getHtmlElement($tagAttributes): string 69604fd306cSNickeau { 69704fd306cSNickeau if ($tagAttributes->hasAttribute("href")) { 69804fd306cSNickeau return "a"; 69904fd306cSNickeau } else { 70004fd306cSNickeau return "button"; 70104fd306cSNickeau } 70204fd306cSNickeau } 70304fd306cSNickeau 7044cadd4f8SNickeau 7054cadd4f8SNickeau} 706