137748cd8SNickeau<?php 237748cd8SNickeau 337748cd8SNickeau 437748cd8SNickeaunamespace ComboStrap; 537748cd8SNickeau 637748cd8SNickeau 7*04fd306cSNickeauuse ComboStrap\Meta\Api\Metadata; 8*04fd306cSNickeauuse ComboStrap\Meta\Api\MetadataText; 937748cd8SNickeauuse dokuwiki\Cache\Cache; 1037748cd8SNickeau 11c3437056SNickeauclass Lang extends MetadataText 1237748cd8SNickeau{ 1337748cd8SNickeau 14c3437056SNickeau public const PROPERTY_NAME = "lang"; 15c3437056SNickeau 1637748cd8SNickeau 1737748cd8SNickeau /** 1837748cd8SNickeau * Process the lang attribute 1937748cd8SNickeau * https://www.w3.org/International/questions/qa-html-language-declarations 2037748cd8SNickeau * @param TagAttributes $attributes 2137748cd8SNickeau * 2237748cd8SNickeau * Language supported: 2337748cd8SNickeau * http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 2437748cd8SNickeau * 2537748cd8SNickeau * Common Locale Data Repository 2637748cd8SNickeau * http://cldr.unicode.org/ 2737748cd8SNickeau * Data: 2837748cd8SNickeau * * http://www.unicode.org/Public/cldr/ 2937748cd8SNickeau * * https://github.com/unicode-cldr/ 3037748cd8SNickeau * * https://github.com/unicode-org/cldr-json 3137748cd8SNickeau * The ''dir'' data is known as the ''characterOrder'' 3237748cd8SNickeau * 3337748cd8SNickeau */ 3437748cd8SNickeau public static function processLangAttribute(&$attributes) 3537748cd8SNickeau { 3637748cd8SNickeau 3737748cd8SNickeau 3837748cd8SNickeau /** 3937748cd8SNickeau * Adding the lang attribute 4037748cd8SNickeau * if set 4137748cd8SNickeau */ 42c3437056SNickeau if ($attributes->hasComponentAttribute(self::PROPERTY_NAME)) { 43c3437056SNickeau $langValue = $attributes->getValueAndRemove(self::PROPERTY_NAME); 444cadd4f8SNickeau $attributes->addOutputAttributeValue("lang", $langValue); 4537748cd8SNickeau 4637748cd8SNickeau $languageDataCache = new Cache("combo_" . $langValue, ".json"); 4737748cd8SNickeau $cacheDataUsable = $languageDataCache->useCache(); 4837748cd8SNickeau if (!$cacheDataUsable) { 4937748cd8SNickeau 5037748cd8SNickeau // Language about the data 5137748cd8SNickeau $downloadUrl = "https://raw.githubusercontent.com/unicode-org/cldr-json/master/cldr-json/cldr-misc-modern/main/$langValue/layout.json"; 5237748cd8SNickeau 53*04fd306cSNickeau if (PluginUtility::isDevOrTest()) { 54*04fd306cSNickeau // phpunit takes over and would catch and cache the error 55*04fd306cSNickeau $filePointer = fopen($downloadUrl, 'r'); 56*04fd306cSNickeau } else { 5737748cd8SNickeau $filePointer = @fopen($downloadUrl, 'r'); 58*04fd306cSNickeau } 5937748cd8SNickeau if ($filePointer != false) { 6037748cd8SNickeau 6137748cd8SNickeau $numberOfByte = @file_put_contents($languageDataCache->cache, $filePointer); 6237748cd8SNickeau if ($numberOfByte != false) { 63c3437056SNickeau LogUtility::msg("The new language data ($langValue) was downloaded", LogUtility::LVL_MSG_INFO, self::PROPERTY_NAME); 6437748cd8SNickeau $cacheDataUsable = true; 6537748cd8SNickeau } else { 66c3437056SNickeau LogUtility::msg("Internal error: The language data ($langValue) could no be written to ($languageDataCache->cache)", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME); 6737748cd8SNickeau } 6837748cd8SNickeau 6937748cd8SNickeau } else { 7037748cd8SNickeau 71*04fd306cSNickeau // fopen(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP? 72*04fd306cSNickeau $error_get_last = error_get_last(); 73*04fd306cSNickeau $message = $error_get_last['message']; 74*04fd306cSNickeau LogUtility::msg("The data for the language ($langValue) could not be downloaded at (<a href=\"$downloadUrl\">$langValue</a>). Error: " . $message, LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME); 7537748cd8SNickeau 7637748cd8SNickeau } 7737748cd8SNickeau } 7837748cd8SNickeau 7937748cd8SNickeau if ($cacheDataUsable) { 8037748cd8SNickeau $jsonAsArray = true; 8137748cd8SNickeau $languageData = json_decode(file_get_contents($languageDataCache->cache), $jsonAsArray); 8237748cd8SNickeau if ($languageData == null) { 83c3437056SNickeau LogUtility::msg("We could not read the data from the language ($langValue). No direction was set.", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME); 8437748cd8SNickeau return; 8537748cd8SNickeau } 8637748cd8SNickeau $characterOrder = $languageData["main"][$langValue]["layout"]["orientation"]["characterOrder"]; 8737748cd8SNickeau if ($characterOrder == "right-to-left") { 884cadd4f8SNickeau $attributes->addOutputAttributeValue("dir", "rtl"); 8937748cd8SNickeau } else { 904cadd4f8SNickeau $attributes->addOutputAttributeValue("dir", "ltr"); 9137748cd8SNickeau } 9237748cd8SNickeau } else { 93c3437056SNickeau LogUtility::msg("The language direction cannot be set because no language data was found for the language ($langValue)", LogUtility::LVL_MSG_WARNING, self::PROPERTY_NAME); 9437748cd8SNickeau } 9537748cd8SNickeau 9637748cd8SNickeau } 9737748cd8SNickeau 9837748cd8SNickeau } 9937748cd8SNickeau 100*04fd306cSNickeau public static function createForMarkup(MarkupPath $markup): Lang 101c3437056SNickeau { 102*04fd306cSNickeau $lang = new Lang(); 103*04fd306cSNickeau $lang->setResource($markup); 104*04fd306cSNickeau return $lang; 105c3437056SNickeau } 106c3437056SNickeau 107*04fd306cSNickeau 108*04fd306cSNickeau /** 109*04fd306cSNickeau * @throws ExceptionNotFound 110*04fd306cSNickeau */ 111*04fd306cSNickeau public static function createFromRequestedMarkup(): Lang 112*04fd306cSNickeau { 113*04fd306cSNickeau return self::createForMarkup(MarkupPath::createFromRequestedPage()); 114*04fd306cSNickeau } 115*04fd306cSNickeau 116*04fd306cSNickeau /** 117*04fd306cSNickeau * Set the direction of the text 118*04fd306cSNickeau * The global lang direction (not yet inside the Lang class) 119*04fd306cSNickeau * @param string $string 120*04fd306cSNickeau * @return void 121*04fd306cSNickeau */ 122*04fd306cSNickeau public static function setDirection(string $string) 123*04fd306cSNickeau { 124*04fd306cSNickeau global $lang; 125*04fd306cSNickeau $lang["direction"] = $string; 126*04fd306cSNickeau } 127*04fd306cSNickeau 128*04fd306cSNickeau public static function createFromValue(string $langValue): Lang 129*04fd306cSNickeau { 130*04fd306cSNickeau $lang = new Lang(); 131*04fd306cSNickeau $lang->value = $langValue; 132*04fd306cSNickeau return $lang; 133*04fd306cSNickeau } 134*04fd306cSNickeau 135*04fd306cSNickeau static public function getTab(): ?string 136c3437056SNickeau { 137c3437056SNickeau return MetaManagerForm::TAB_LANGUAGE_VALUE; 138c3437056SNickeau } 139c3437056SNickeau 140c3437056SNickeau /** 141*04fd306cSNickeau * @return string 142*04fd306cSNickeau */ 143*04fd306cSNickeau public function getValueOrDefault(): string 144*04fd306cSNickeau { 145*04fd306cSNickeau try { 146*04fd306cSNickeau return $this->getValue(); 147*04fd306cSNickeau } catch (ExceptionNotFound $e) { 148*04fd306cSNickeau return $this->getDefaultValue(); 149*04fd306cSNickeau } 150*04fd306cSNickeau } 151*04fd306cSNickeau 152*04fd306cSNickeau 153*04fd306cSNickeau /** 154*04fd306cSNickeau * @throws ExceptionCompile 155c3437056SNickeau */ 156c3437056SNickeau public function setFromStoreValue($value): Metadata 157c3437056SNickeau { 158c3437056SNickeau 159c3437056SNickeau $this->validityCheck($value); 160c3437056SNickeau return parent::setFromStoreValue($value); 161c3437056SNickeau 162c3437056SNickeau } 163c3437056SNickeau 164c3437056SNickeau /** 165c3437056SNickeau * @param string|null $value 166c3437056SNickeau * @return Metadata 167*04fd306cSNickeau * @throws ExceptionCompile 168c3437056SNickeau */ 169c3437056SNickeau public function setValue($value): Metadata 170c3437056SNickeau { 171c3437056SNickeau $this->validityCheck($value); 172c3437056SNickeau return parent::setValue($value); 173c3437056SNickeau } 174c3437056SNickeau 175c3437056SNickeau 176*04fd306cSNickeau static public function getDescription(): string 177c3437056SNickeau { 178c3437056SNickeau return "The language of the page"; 179c3437056SNickeau } 180c3437056SNickeau 181*04fd306cSNickeau static public function getLabel(): string 182c3437056SNickeau { 183c3437056SNickeau return "Language"; 184c3437056SNickeau } 185c3437056SNickeau 186c3437056SNickeau public static function getName(): string 187c3437056SNickeau { 188c3437056SNickeau return self::PROPERTY_NAME; 189c3437056SNickeau } 190c3437056SNickeau 191*04fd306cSNickeau static public function getPersistenceType(): string 192c3437056SNickeau { 193c3437056SNickeau return Metadata::PERSISTENT_METADATA; 194c3437056SNickeau } 195c3437056SNickeau 196*04fd306cSNickeau static public function isMutable(): bool 197c3437056SNickeau { 198c3437056SNickeau return true; 199c3437056SNickeau } 200c3437056SNickeau 201*04fd306cSNickeau /** 202*04fd306cSNickeau * @return string 203*04fd306cSNickeau */ 204*04fd306cSNickeau public function getDefaultValue(): string 205c3437056SNickeau { 206c3437056SNickeau return Site::getLang(); 207c3437056SNickeau } 208c3437056SNickeau 209c3437056SNickeau /** 210*04fd306cSNickeau * @throws ExceptionCompile 211c3437056SNickeau */ 212c3437056SNickeau private function validityCheck($value) 213c3437056SNickeau { 214c3437056SNickeau if ($value === "" || $value === null) { 215c3437056SNickeau return; 216c3437056SNickeau } 217c3437056SNickeau if (!StringUtility::match($value, "^[a-zA-Z]{2}$")) { 218*04fd306cSNickeau throw new ExceptionCompile("The lang value ($value) for the page ($this) does not have two letters", $this->getCanonical()); 219c3437056SNickeau } 220c3437056SNickeau } 221c3437056SNickeau 222*04fd306cSNickeau static public function getCanonical(): string 223c3437056SNickeau { 224c3437056SNickeau return "lang"; 225c3437056SNickeau } 226c3437056SNickeau 227*04fd306cSNickeau public function getDirection() 228*04fd306cSNickeau { 229*04fd306cSNickeau /** 230*04fd306cSNickeau * TODO: should be base on the page value 231*04fd306cSNickeau * Search PHP and CLDR 232*04fd306cSNickeau * https://punic.github.io/ 233*04fd306cSNickeau * https://www.php.net/manual/en/book.intl.php 234*04fd306cSNickeau * 235*04fd306cSNickeau * Example: 236*04fd306cSNickeau * https://github.com/salarmehr/cosmopolitan 237*04fd306cSNickeau * use Salarmehr\Cosmopolitan\Cosmo; 238*04fd306cSNickeau * 239*04fd306cSNickeau * echo Cosmo::create('fa')->direction(); // rlt 240*04fd306cSNickeau * echo Cosmo::create('en')->direction(); // ltr 241*04fd306cSNickeau */ 242*04fd306cSNickeau return Site::getLangDirection(); 243*04fd306cSNickeau } 244*04fd306cSNickeau 245*04fd306cSNickeau 246*04fd306cSNickeau static public function isOnForm(): bool 247*04fd306cSNickeau { 248*04fd306cSNickeau return true; 249*04fd306cSNickeau } 250c3437056SNickeau 25137748cd8SNickeau} 252