xref: /plugin/combo/ComboStrap/Lang.php (revision f47bee6b7ae37ddc20ceeb12934c14a2a02bfe2a)
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