xref: /plugin/combo/ComboStrap/Lang.php (revision 498fa0113a012c04e87cf1e6ac006025888a6cb8)
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";
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
51*498fa011SNicolas GERARD                $downloadUrl = "https://raw.githubusercontent.com/unicode-org/cldr-json/refs/tags/47.0.0/cldr-json/cldr-misc-full/main/$langValue/layout.json";
5237748cd8SNickeau
5304fd306cSNickeau                if (PluginUtility::isDevOrTest()) {
5404fd306cSNickeau                    // phpunit takes over and would catch and cache the error
5504fd306cSNickeau                    $filePointer = fopen($downloadUrl, 'r');
5604fd306cSNickeau                } else {
5737748cd8SNickeau                    $filePointer = @fopen($downloadUrl, 'r');
5804fd306cSNickeau                }
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
7104fd306cSNickeau                    // fopen(): Unable to find the wrapper "https" - did you forget to enable it when you configured PHP?
7204fd306cSNickeau                    $error_get_last = error_get_last();
7304fd306cSNickeau                    $message = $error_get_last['message'];
7404fd306cSNickeau                    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
10004fd306cSNickeau    public static function createForMarkup(MarkupPath $markup): Lang
101c3437056SNickeau    {
10204fd306cSNickeau        $lang = new Lang();
10304fd306cSNickeau        $lang->setResource($markup);
10404fd306cSNickeau        return $lang;
105c3437056SNickeau    }
106c3437056SNickeau
10704fd306cSNickeau
10804fd306cSNickeau    /**
10904fd306cSNickeau     * @throws ExceptionNotFound
11004fd306cSNickeau     */
11104fd306cSNickeau    public static function createFromRequestedMarkup(): Lang
11204fd306cSNickeau    {
11304fd306cSNickeau        return self::createForMarkup(MarkupPath::createFromRequestedPage());
11404fd306cSNickeau    }
11504fd306cSNickeau
11604fd306cSNickeau    /**
11704fd306cSNickeau     * Set the direction of the text
11804fd306cSNickeau     * The global lang direction (not yet inside the Lang class)
11904fd306cSNickeau     * @param string $string
12004fd306cSNickeau     * @return void
12104fd306cSNickeau     */
12204fd306cSNickeau    public static function setDirection(string $string)
12304fd306cSNickeau    {
12404fd306cSNickeau        global $lang;
12504fd306cSNickeau        $lang["direction"] = $string;
12604fd306cSNickeau    }
12704fd306cSNickeau
12804fd306cSNickeau    public static function createFromValue(string $langValue): Lang
12904fd306cSNickeau    {
13004fd306cSNickeau        $lang = new Lang();
13104fd306cSNickeau        $lang->value = $langValue;
13204fd306cSNickeau        return $lang;
13304fd306cSNickeau    }
13404fd306cSNickeau
13504fd306cSNickeau    static public function getTab(): ?string
136c3437056SNickeau    {
137c3437056SNickeau        return MetaManagerForm::TAB_LANGUAGE_VALUE;
138c3437056SNickeau    }
139c3437056SNickeau
140c3437056SNickeau    /**
14104fd306cSNickeau     * @return string
14204fd306cSNickeau     */
14304fd306cSNickeau    public function getValueOrDefault(): string
14404fd306cSNickeau    {
14504fd306cSNickeau        try {
14604fd306cSNickeau            return $this->getValue();
14704fd306cSNickeau        } catch (ExceptionNotFound $e) {
14804fd306cSNickeau            return $this->getDefaultValue();
14904fd306cSNickeau        }
15004fd306cSNickeau    }
15104fd306cSNickeau
15204fd306cSNickeau
15304fd306cSNickeau    /**
15404fd306cSNickeau     * @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
16704fd306cSNickeau     * @throws ExceptionCompile
168c3437056SNickeau     */
169c3437056SNickeau    public function setValue($value): Metadata
170c3437056SNickeau    {
171c3437056SNickeau        $this->validityCheck($value);
172c3437056SNickeau        return parent::setValue($value);
173c3437056SNickeau    }
174c3437056SNickeau
175c3437056SNickeau
17604fd306cSNickeau    static public function getDescription(): string
177c3437056SNickeau    {
178c3437056SNickeau        return "The language of the page";
179c3437056SNickeau    }
180c3437056SNickeau
18104fd306cSNickeau    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
19104fd306cSNickeau    static public function getPersistenceType(): string
192c3437056SNickeau    {
193c3437056SNickeau        return Metadata::PERSISTENT_METADATA;
194c3437056SNickeau    }
195c3437056SNickeau
19604fd306cSNickeau    static public function isMutable(): bool
197c3437056SNickeau    {
198c3437056SNickeau        return true;
199c3437056SNickeau    }
200c3437056SNickeau
20104fd306cSNickeau    /**
20204fd306cSNickeau     * @return string
20304fd306cSNickeau     */
20404fd306cSNickeau    public function getDefaultValue(): string
205c3437056SNickeau    {
206c3437056SNickeau        return Site::getLang();
207c3437056SNickeau    }
208c3437056SNickeau
209c3437056SNickeau    /**
21004fd306cSNickeau     * @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}$")) {
21804fd306cSNickeau            throw new ExceptionCompile("The lang value ($value) for the page ($this) does not have two letters", $this->getCanonical());
219c3437056SNickeau        }
220c3437056SNickeau    }
221c3437056SNickeau
22204fd306cSNickeau    static public function getCanonical(): string
223c3437056SNickeau    {
224c3437056SNickeau        return "lang";
225c3437056SNickeau    }
226c3437056SNickeau
22704fd306cSNickeau    public function getDirection()
22804fd306cSNickeau    {
22904fd306cSNickeau        /**
23004fd306cSNickeau         * TODO: should be base on the page value
23104fd306cSNickeau         * Search PHP and CLDR
23204fd306cSNickeau         * https://punic.github.io/
23304fd306cSNickeau         * https://www.php.net/manual/en/book.intl.php
23404fd306cSNickeau         *
23504fd306cSNickeau         * Example:
23604fd306cSNickeau         * https://github.com/salarmehr/cosmopolitan
23704fd306cSNickeau         * use Salarmehr\Cosmopolitan\Cosmo;
23804fd306cSNickeau         *
23904fd306cSNickeau         * echo Cosmo::create('fa')->direction(); // rlt
24004fd306cSNickeau         * echo Cosmo::create('en')->direction(); // ltr
24104fd306cSNickeau         */
24204fd306cSNickeau        return Site::getLangDirection();
24304fd306cSNickeau    }
24404fd306cSNickeau
24504fd306cSNickeau
24604fd306cSNickeau    static public function isOnForm(): bool
24704fd306cSNickeau    {
24804fd306cSNickeau        return true;
24904fd306cSNickeau    }
250c3437056SNickeau
25137748cd8SNickeau}
252