1<?php
2
3
4namespace ComboStrap;
5
6
7use dokuwiki\Cache\Cache;
8
9class Lang extends MetadataText
10{
11
12    public const PROPERTY_NAME = "lang";
13
14
15    /**
16     * Process the lang attribute
17     * https://www.w3.org/International/questions/qa-html-language-declarations
18     * @param TagAttributes $attributes
19     *
20     * Language supported:
21     * http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
22     *
23     * Common Locale Data Repository
24     * http://cldr.unicode.org/
25     * Data:
26     *   * http://www.unicode.org/Public/cldr/
27     *   * https://github.com/unicode-cldr/
28     *   * https://github.com/unicode-org/cldr-json
29     * The ''dir'' data is known as the ''characterOrder''
30     *
31     */
32    public static function processLangAttribute(&$attributes)
33    {
34
35
36        /**
37         * Adding the lang attribute
38         * if set
39         */
40        if ($attributes->hasComponentAttribute(self::PROPERTY_NAME)) {
41            $langValue = $attributes->getValueAndRemove(self::PROPERTY_NAME);
42            $attributes->addHtmlAttributeValue("lang", $langValue);
43
44            $languageDataCache = new Cache("combo_" . $langValue, ".json");
45            $cacheDataUsable = $languageDataCache->useCache();
46            if (!$cacheDataUsable) {
47
48                // Language about the data
49                $downloadUrl = "https://raw.githubusercontent.com/unicode-org/cldr-json/master/cldr-json/cldr-misc-modern/main/$langValue/layout.json";
50
51                $filePointer = @fopen($downloadUrl, 'r');
52                if ($filePointer != false) {
53
54                    $numberOfByte = @file_put_contents($languageDataCache->cache, $filePointer);
55                    if ($numberOfByte != false) {
56                        LogUtility::msg("The new language data ($langValue) was downloaded", LogUtility::LVL_MSG_INFO, self::PROPERTY_NAME);
57                        $cacheDataUsable = true;
58                    } else {
59                        LogUtility::msg("Internal error: The language data ($langValue) could no be written to ($languageDataCache->cache)", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME);
60                    }
61
62                } else {
63
64                    LogUtility::msg("The data for the language ($langValue) could not be found at ($downloadUrl).", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME);
65
66                }
67            }
68
69            if ($cacheDataUsable) {
70                $jsonAsArray = true;
71                $languageData = json_decode(file_get_contents($languageDataCache->cache), $jsonAsArray);
72                if ($languageData == null) {
73                    LogUtility::msg("We could not read the data from the language ($langValue). No direction was set.", LogUtility::LVL_MSG_ERROR, self::PROPERTY_NAME);
74                    return;
75                }
76                $characterOrder = $languageData["main"][$langValue]["layout"]["orientation"]["characterOrder"];
77                if ($characterOrder == "right-to-left") {
78                    $attributes->addHtmlAttributeValue("dir", "rtl");
79                } else {
80                    $attributes->addHtmlAttributeValue("dir", "ltr");
81                }
82            } else {
83                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);
84            }
85
86        }
87
88    }
89
90    public static function createForPage(Page $page)
91    {
92        return (new Lang())
93            ->setResource($page);
94    }
95
96    public function getTab(): ?string
97    {
98        return MetaManagerForm::TAB_LANGUAGE_VALUE;
99    }
100
101    /**
102     * @throws ExceptionCombo
103     */
104    public function setFromStoreValue($value): Metadata
105    {
106
107        $this->validityCheck($value);
108        return parent::setFromStoreValue($value);
109
110    }
111
112    /**
113     * @param string|null $value
114     * @return Metadata
115     * @throws ExceptionCombo
116     */
117    public function setValue($value): Metadata
118    {
119        $this->validityCheck($value);
120        return parent::setValue($value);
121    }
122
123
124    public function getDescription(): string
125    {
126        return "The language of the page";
127    }
128
129    public function getLabel(): string
130    {
131        return "Language";
132    }
133
134    public static function getName(): string
135    {
136        return self::PROPERTY_NAME;
137    }
138
139    public function getPersistenceType(): string
140    {
141        return Metadata::PERSISTENT_METADATA;
142    }
143
144    public function getMutable(): bool
145    {
146        return true;
147    }
148
149    public function getDefaultValue()
150    {
151        return Site::getLang();
152    }
153
154    /**
155     * @throws ExceptionCombo
156     */
157    private function validityCheck($value)
158    {
159        if ($value === "" || $value === null) {
160            return;
161        }
162        if (!StringUtility::match($value, "^[a-zA-Z]{2}$")) {
163            throw new ExceptionCombo("The lang value ($value) for the page ($this) does not have two letters", $this->getCanonical());
164        }
165    }
166
167    public function getCanonical(): string
168    {
169        return "lang";
170    }
171
172
173}
174