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