137748cd8SNickeau<?php 237748cd8SNickeau 337748cd8SNickeau 437748cd8SNickeaunamespace ComboStrap; 537748cd8SNickeau 637748cd8SNickeau 704fd306cSNickeauuse ComboStrap\Meta\Api\Metadata; 804fd306cSNickeauuse ComboStrap\Meta\Api\MetadataText; 937748cd8SNickeauuse dokuwiki\Cache\Cache; 1037748cd8SNickeau 11c3437056SNickeauclass Lang extends MetadataText 1237748cd8SNickeau{ 1337748cd8SNickeau 14c3437056SNickeau public const PROPERTY_NAME = "lang"; 15*f47bee6bSNicolas GERARD public const PROPERTY_DIR_NAME = "dir"; 16c3437056SNickeau 1737748cd8SNickeau 1837748cd8SNickeau /** 1937748cd8SNickeau * Process the lang attribute 2037748cd8SNickeau * https://www.w3.org/International/questions/qa-html-language-declarations 2137748cd8SNickeau * @param TagAttributes $attributes 2237748cd8SNickeau * 2337748cd8SNickeau * Language supported: 2437748cd8SNickeau * http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry 2537748cd8SNickeau * 2637748cd8SNickeau * Common Locale Data Repository 2737748cd8SNickeau * http://cldr.unicode.org/ 2837748cd8SNickeau * Data: 2937748cd8SNickeau * * http://www.unicode.org/Public/cldr/ 3037748cd8SNickeau * * https://github.com/unicode-cldr/ 3137748cd8SNickeau * * https://github.com/unicode-org/cldr-json 3237748cd8SNickeau * The ''dir'' data is known as the ''characterOrder'' 3337748cd8SNickeau * 3437748cd8SNickeau */ 3537748cd8SNickeau public static function processLangAttribute(&$attributes) 3637748cd8SNickeau { 3737748cd8SNickeau 3837748cd8SNickeau 3937748cd8SNickeau /** 4037748cd8SNickeau * Adding the lang attribute 4137748cd8SNickeau * if set 4237748cd8SNickeau */ 43c3437056SNickeau if ($attributes->hasComponentAttribute(self::PROPERTY_NAME)) { 44c3437056SNickeau $langValue = $attributes->getValueAndRemove(self::PROPERTY_NAME); 454cadd4f8SNickeau $attributes->addOutputAttributeValue("lang", $langValue); 4637748cd8SNickeau 4737748cd8SNickeau $languageDataCache = new Cache("combo_" . $langValue, ".json"); 4837748cd8SNickeau $cacheDataUsable = $languageDataCache->useCache(); 4937748cd8SNickeau if (!$cacheDataUsable) { 5037748cd8SNickeau 5137748cd8SNickeau // Language about the data 52498fa011SNicolas GERARD $downloadUrl = "https://raw.githubusercontent.com/unicode-org/cldr-json/refs/tags/47.0.0/cldr-json/cldr-misc-full/main/$langValue/layout.json"; 5337748cd8SNickeau 5404fd306cSNickeau if (PluginUtility::isDevOrTest()) { 5504fd306cSNickeau // phpunit takes over and would catch and cache the error 5604fd306cSNickeau $filePointer = fopen($downloadUrl, 'r'); 5704fd306cSNickeau } else { 5837748cd8SNickeau $filePointer = @fopen($downloadUrl, 'r'); 5904fd306cSNickeau } 6037748cd8SNickeau if ($filePointer != false) { 6137748cd8SNickeau 6237748cd8SNickeau $numberOfByte = @file_put_contents($languageDataCache->cache, $filePointer); 6337748cd8SNickeau if ($numberOfByte != false) { 64c3437056SNickeau LogUtility::msg("The new language data ($langValue) was downloaded", LogUtility::LVL_MSG_INFO, self::PROPERTY_NAME); 6537748cd8SNickeau $cacheDataUsable = true; 6637748cd8SNickeau } else { 67c3437056SNickeau LogUtility::msg("Internal error: The language data ($langValue) could no be written to ($languageDataCache->cache)", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME); 6837748cd8SNickeau } 6937748cd8SNickeau 7037748cd8SNickeau } else { 7137748cd8SNickeau 7204fd306cSNickeau // fopen(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP? 7304fd306cSNickeau $error_get_last = error_get_last(); 7404fd306cSNickeau $message = $error_get_last['message']; 7504fd306cSNickeau 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); 7637748cd8SNickeau 7737748cd8SNickeau } 7837748cd8SNickeau } 7937748cd8SNickeau 8037748cd8SNickeau if ($cacheDataUsable) { 8137748cd8SNickeau $jsonAsArray = true; 8237748cd8SNickeau $languageData = json_decode(file_get_contents($languageDataCache->cache), $jsonAsArray); 8337748cd8SNickeau if ($languageData == null) { 84c3437056SNickeau LogUtility::msg("We could not read the data from the language ($langValue). No direction was set.", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME); 8537748cd8SNickeau return; 8637748cd8SNickeau } 8737748cd8SNickeau $characterOrder = $languageData["main"][$langValue]["layout"]["orientation"]["characterOrder"]; 8837748cd8SNickeau if ($characterOrder == "right-to-left") { 894cadd4f8SNickeau $attributes->addOutputAttributeValue("dir", "rtl"); 9037748cd8SNickeau } else { 914cadd4f8SNickeau $attributes->addOutputAttributeValue("dir", "ltr"); 9237748cd8SNickeau } 9337748cd8SNickeau } else { 94c3437056SNickeau 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); 9537748cd8SNickeau } 9637748cd8SNickeau 9737748cd8SNickeau } 9837748cd8SNickeau 9937748cd8SNickeau } 10037748cd8SNickeau 10104fd306cSNickeau public static function createForMarkup(MarkupPath $markup): Lang 102c3437056SNickeau { 10304fd306cSNickeau $lang = new Lang(); 10404fd306cSNickeau $lang->setResource($markup); 10504fd306cSNickeau return $lang; 106c3437056SNickeau } 107c3437056SNickeau 10804fd306cSNickeau 10904fd306cSNickeau /** 11004fd306cSNickeau * @throws ExceptionNotFound 11104fd306cSNickeau */ 11204fd306cSNickeau public static function createFromRequestedMarkup(): Lang 11304fd306cSNickeau { 11404fd306cSNickeau return self::createForMarkup(MarkupPath::createFromRequestedPage()); 11504fd306cSNickeau } 11604fd306cSNickeau 11704fd306cSNickeau /** 11804fd306cSNickeau * Set the direction of the text 11904fd306cSNickeau * The global lang direction (not yet inside the Lang class) 12004fd306cSNickeau * @param string $string 12104fd306cSNickeau * @return void 12204fd306cSNickeau */ 12304fd306cSNickeau public static function setDirection(string $string) 12404fd306cSNickeau { 12504fd306cSNickeau global $lang; 12604fd306cSNickeau $lang["direction"] = $string; 12704fd306cSNickeau } 12804fd306cSNickeau 12904fd306cSNickeau public static function createFromValue(string $langValue): Lang 13004fd306cSNickeau { 13104fd306cSNickeau $lang = new Lang(); 13204fd306cSNickeau $lang->value = $langValue; 13304fd306cSNickeau return $lang; 13404fd306cSNickeau } 13504fd306cSNickeau 13604fd306cSNickeau static public function getTab(): ?string 137c3437056SNickeau { 138c3437056SNickeau return MetaManagerForm::TAB_LANGUAGE_VALUE; 139c3437056SNickeau } 140c3437056SNickeau 141c3437056SNickeau /** 14204fd306cSNickeau * @return string 14304fd306cSNickeau */ 14404fd306cSNickeau public function getValueOrDefault(): string 14504fd306cSNickeau { 14604fd306cSNickeau try { 14704fd306cSNickeau return $this->getValue(); 14804fd306cSNickeau } catch (ExceptionNotFound $e) { 14904fd306cSNickeau return $this->getDefaultValue(); 15004fd306cSNickeau } 15104fd306cSNickeau } 15204fd306cSNickeau 15304fd306cSNickeau 15404fd306cSNickeau /** 15504fd306cSNickeau * @throws ExceptionCompile 156c3437056SNickeau */ 157c3437056SNickeau public function setFromStoreValue($value): Metadata 158c3437056SNickeau { 159c3437056SNickeau 160c3437056SNickeau $this->validityCheck($value); 161c3437056SNickeau return parent::setFromStoreValue($value); 162c3437056SNickeau 163c3437056SNickeau } 164c3437056SNickeau 165c3437056SNickeau /** 166c3437056SNickeau * @param string|null $value 167c3437056SNickeau * @return Metadata 16804fd306cSNickeau * @throws ExceptionCompile 169c3437056SNickeau */ 170c3437056SNickeau public function setValue($value): Metadata 171c3437056SNickeau { 172c3437056SNickeau $this->validityCheck($value); 173c3437056SNickeau return parent::setValue($value); 174c3437056SNickeau } 175c3437056SNickeau 176c3437056SNickeau 17704fd306cSNickeau static public function getDescription(): string 178c3437056SNickeau { 179c3437056SNickeau return "The language of the page"; 180c3437056SNickeau } 181c3437056SNickeau 18204fd306cSNickeau static public function getLabel(): string 183c3437056SNickeau { 184c3437056SNickeau return "Language"; 185c3437056SNickeau } 186c3437056SNickeau 187c3437056SNickeau public static function getName(): string 188c3437056SNickeau { 189c3437056SNickeau return self::PROPERTY_NAME; 190c3437056SNickeau } 191c3437056SNickeau 19204fd306cSNickeau static public function getPersistenceType(): string 193c3437056SNickeau { 194c3437056SNickeau return Metadata::PERSISTENT_METADATA; 195c3437056SNickeau } 196c3437056SNickeau 19704fd306cSNickeau static public function isMutable(): bool 198c3437056SNickeau { 199c3437056SNickeau return true; 200c3437056SNickeau } 201c3437056SNickeau 20204fd306cSNickeau /** 20304fd306cSNickeau * @return string 20404fd306cSNickeau */ 20504fd306cSNickeau public function getDefaultValue(): string 206c3437056SNickeau { 207c3437056SNickeau return Site::getLang(); 208c3437056SNickeau } 209c3437056SNickeau 210c3437056SNickeau /** 21104fd306cSNickeau * @throws ExceptionCompile 212c3437056SNickeau */ 213c3437056SNickeau private function validityCheck($value) 214c3437056SNickeau { 215c3437056SNickeau if ($value === "" || $value === null) { 216c3437056SNickeau return; 217c3437056SNickeau } 218c3437056SNickeau if (!StringUtility::match($value, "^[a-zA-Z]{2}$")) { 21904fd306cSNickeau throw new ExceptionCompile("The lang value ($value) for the page ($this) does not have two letters", $this->getCanonical()); 220c3437056SNickeau } 221c3437056SNickeau } 222c3437056SNickeau 22304fd306cSNickeau static public function getCanonical(): string 224c3437056SNickeau { 225c3437056SNickeau return "lang"; 226c3437056SNickeau } 227c3437056SNickeau 22804fd306cSNickeau public function getDirection() 22904fd306cSNickeau { 23004fd306cSNickeau /** 23104fd306cSNickeau * TODO: should be base on the page value 23204fd306cSNickeau * Search PHP and CLDR 23304fd306cSNickeau * https://punic.github.io/ 23404fd306cSNickeau * https://www.php.net/manual/en/book.intl.php 23504fd306cSNickeau * 23604fd306cSNickeau * Example: 23704fd306cSNickeau * https://github.com/salarmehr/cosmopolitan 23804fd306cSNickeau * use Salarmehr\Cosmopolitan\Cosmo; 23904fd306cSNickeau * 24004fd306cSNickeau * echo Cosmo::create('fa')->direction(); // rlt 24104fd306cSNickeau * echo Cosmo::create('en')->direction(); // ltr 24204fd306cSNickeau */ 24304fd306cSNickeau return Site::getLangDirection(); 24404fd306cSNickeau } 24504fd306cSNickeau 24604fd306cSNickeau 24704fd306cSNickeau static public function isOnForm(): bool 24804fd306cSNickeau { 24904fd306cSNickeau return true; 25004fd306cSNickeau } 251c3437056SNickeau 25237748cd8SNickeau} 253