1<?php 2 3 4namespace ComboStrap; 5 6 7class Brand 8{ 9 10 const NEWSLETTER_BRAND_NAME = "newsletter"; 11 const EMAIL_BRAND_NAME = "email"; 12 13 14 /** 15 * The brand of the current application/website 16 */ 17 public const CURRENT_BRAND = "current"; 18 const CANONICAL = "brand"; 19 const ABBR_PROPERTY = 'abbr'; 20 /** 21 * @var array an array of brand abbreviation as key and their name as value 22 */ 23 private static array $BRAND_ABBR; 24 25 26 private $secondaryColor; 27 private $brandUrl; 28 29 /** 30 * @var array 31 */ 32 public static array $brandDictionary; 33 /** 34 * @var bool 35 */ 36 private bool $unknown = false; 37 /** 38 * @var mixed 39 */ 40 private $brandDict; 41 42 43 /** 44 * Brand constructor. 45 * @param string $name 46 */ 47 private function __construct(string $name) 48 { 49 50 $this->name = $name; 51 52 /** 53 * Get the brands 54 */ 55 $brandDictionary = Brand::getBrandDictionary(); 56 57 58 /** 59 * Build the data for the brand 60 */ 61 $this->brandDict = $brandDictionary[$this->name] ?? null; 62 switch ($this->name) { 63 case self::CURRENT_BRAND: 64 $this->brandUrl = Site::getBaseUrl(); 65 $secondaryColor = Site::getSecondaryColor(); 66 if ($secondaryColor !== null) { 67 // the predicates on the secondary value is to avoid a loop with the the function below 68 $this->secondaryColor = $secondaryColor->toCssValue(); 69 } 70 break; 71 default: 72 if ($this->brandDict !== null) { 73 $colors = $this->brandDict["colors"] ?? null; 74 if ($colors !== null) { 75 $this->secondaryColor = $colors["secondary"]; 76 } else { 77 $this->secondaryColor = null; 78 } 79 $this->brandUrl = $this->brandDict["url"] ?? null; 80 return; 81 } 82 $this->unknown = true; 83 break; 84 } 85 86 } 87 88 /** 89 * @return string[] 90 */ 91 public static function getAllKnownBrandNames(): array 92 { 93 94 $brands = self::getAllBrands(); 95 $brandNames = [self::CURRENT_BRAND]; 96 foreach ($brands as $brand) { 97 $brandNames[] = $brand->getName(); 98 try { 99 $brandNames[] = $brand->getAbbr(); 100 } catch (ExceptionNotFound $e) { 101 // ok 102 } 103 } 104 return $brandNames; 105 106 } 107 108 109 /** 110 * @return Brand[] 111 */ 112 public static function getAllBrands(): array 113 { 114 $brandDictionary = self::getBrandDictionary(); 115 $brands = []; 116 foreach (array_keys($brandDictionary) as $brandName) { 117 $brands[] = self::create($brandName); 118 } 119 return $brands; 120 } 121 122 /** 123 * @param $type - the button type (ie one of {@link BrandButton::TYPE_BUTTONS} 124 * @return array - the brand names that can be used as type in the brand button 125 */ 126 public static function getBrandNamesForButtonType($type): array 127 { 128 $brands = self::getAllBrands(); 129 $brandNamesForType = []; 130 foreach ($brands as $brand) { 131 if ($brand->supportButtonType($type)) { 132 $brandNamesForType[] = $brand->getName(); 133 try { 134 $brandNamesForType[] = $brand->getAbbr(); 135 } catch (ExceptionNotFound $e) { 136 // ok 137 } 138 } 139 } 140 return $brandNamesForType; 141 } 142 143 /** 144 * 145 */ 146 public static function getBrandDictionary(): array 147 { 148 if (!isset(Brand::$brandDictionary)) { 149 try { 150 Brand::$brandDictionary = Dictionary::getFrom("brands"); 151 } catch (ExceptionCompile $e) { 152 // Should never happens 153 Brand::$brandDictionary = []; 154 LogUtility::error("We can't load the brands dictionary. Error: " . $e->getMessage(), self::CANONICAL, $e); 155 } 156 } 157 return Brand::$brandDictionary; 158 } 159 160 161 /** 162 * @var string 163 * The name of the brand, 164 * for company, we follow the naming of 165 * https://github.com/ellisonleao/sharer.js 166 */ 167 private $name; 168 169 170 public static function create(string $brandName): Brand 171 { 172 173 $brandNameQualified = strtolower($brandName); 174 $brandNameQualified = Brand::getBrandNameFromAbbr($brandNameQualified); 175 $objectIdentifier = self::CANONICAL . "-" . $brandNameQualified; 176 $executionContext = ExecutionContext::getActualOrCreateFromEnv(); 177 try { 178 return $executionContext->getRuntimeObject($objectIdentifier); 179 } catch (ExceptionNotFound $e) { 180 $brandObject = new Brand($brandNameQualified); 181 $executionContext->setRuntimeObject($objectIdentifier, $brandObject); 182 return $brandObject; 183 } 184 185 } 186 187 private static function getBrandNameFromAbbr(string $name) 188 { 189 if (!isset(self::$BRAND_ABBR)) { 190 $brandDictionary = self::getBrandDictionary(); 191 foreach ($brandDictionary as $brandName => $brandProperties) { 192 $abbr = $brandProperties[self::ABBR_PROPERTY] ?? null; 193 if (empty($abbr)) { 194 continue; 195 } 196 self::$BRAND_ABBR[$abbr] = $brandName; 197 } 198 } 199 if (isset(self::$BRAND_ABBR[$name])) { 200 return self::$BRAND_ABBR[$name]; 201 } 202 return $name; 203 204 } 205 206 207 /** 208 * If the brand name is unknown (ie custom) 209 * @return bool 210 */ 211 public function isUnknown(): bool 212 { 213 return $this->unknown; 214 215 } 216 217 public function getName(): string 218 { 219 return $this->name; 220 } 221 222 public function __toString() 223 { 224 if ($this->name === Brand::CURRENT_BRAND) { 225 return $this->name . " (" . Site::getTitle() . ")"; 226 } 227 return $this->name; 228 } 229 230 /** 231 * Shared/Follow Url template 232 * the endpoint template url (for sharing and following) 233 * @var string $type - the type of button 234 */ 235 public function getWebUrlTemplate(string $type): ?string 236 { 237 if (isset($this->brandDict[$type])) { 238 return $this->brandDict[$type]["web"]; 239 } 240 return null; 241 } 242 243 /** 244 * Brand button title 245 * @return string 246 * @var ?string $type - the button type 247 */ 248 public function getTitle(string $type = null): ?string 249 { 250 if ($this->name === self::CURRENT_BRAND) { 251 return Site::getTitle(); 252 } 253 if ($this->brandDict !== null && $type !== null) { 254 if (isset($this->brandDict[$type])) { 255 return $this->brandDict[$type]["popup"]; 256 } 257 } 258 return null; 259 260 } 261 262 public function getPrimaryColor(): ?string 263 { 264 265 if ($this->brandDict !== null) { 266 $primaryColor = $this->brandDict["colors"]["primary"]; 267 if ($primaryColor !== null) { 268 return $primaryColor; 269 } 270 } 271 272 // Unknown or current brand / unknown color 273 try { 274 return ExecutionContext::getExecutionContext() 275 ->getConfig() 276 ->getPrimaryColor(); 277 } catch (ExceptionNotFound $e) { 278 return null; 279 } 280 281 } 282 283 public function getSecondaryColor(): ?string 284 { 285 return $this->secondaryColor; 286 } 287 288 /** 289 * @param string|null $type - the button type 290 * @return string|null 291 */ 292 public function getIconName(?string $type): ?string 293 { 294 295 switch ($this->name) { 296 case self::CURRENT_BRAND: 297 try { 298 return Site::getLogoAsSvgImage() 299 ->getWikiId(); 300 } catch (ExceptionNotFound $e) { 301 // no logo installed 302 } 303 break; 304 default: 305 if (isset($this->brandDict["icons"])) { 306 return $this->brandDict["icons"][$type]; 307 } 308 break; 309 } 310 311 return null; 312 } 313 314 public function getBrandUrl(): ?string 315 { 316 return $this->brandUrl; 317 } 318 319 /** 320 */ 321 public function supportButtonType(string $type): bool 322 { 323 switch ($type) { 324 case BrandButton::TYPE_BUTTON_SHARE: 325 case BrandButton::TYPE_BUTTON_FOLLOW: 326 if ($this->getWebUrlTemplate($type) !== null) { 327 return true; 328 } 329 return false; 330 default: 331 case BrandButton::TYPE_BUTTON_BRAND: 332 return true; 333 } 334 } 335 336 /** 337 * @throws ExceptionNotFound 338 */ 339 private function getAbbr() 340 { 341 $value = $this->brandDict['abbr'] ?? null; 342 if (empty($value)) { 343 throw new ExceptionNotFound("No abbreviations"); 344 } 345 return $value; 346 } 347 348 349} 350