1 | <?php |
---|
2 | /** |
---|
3 | * Ce fichier contient l'ensemble des constantes et fonctions implémentant les services ISO. |
---|
4 | * |
---|
5 | * @package SPIP\CODELANG\SERVICES\ISO |
---|
6 | */ |
---|
7 | if (!defined('_ECRIRE_INC_VERSION')) { |
---|
8 | return; |
---|
9 | } |
---|
10 | |
---|
11 | |
---|
12 | if (!defined('_CODELANG_SIL_ISO639_3_ENDPOINT')) { |
---|
13 | /** |
---|
14 | * URL de base pour charger la page de documentation d'un code de langue alpha-3 sur le site |
---|
15 | * sil.org |
---|
16 | */ |
---|
17 | define('_CODELANG_SIL_ISO639_3_ENDPOINT', 'http://www-01.sil.org/iso639-3/documentation.asp?id='); |
---|
18 | } |
---|
19 | if (!defined('_CODELANG_LOC_ISO639_5_HIERARCHY')) { |
---|
20 | /** |
---|
21 | * URL de base pour charger la page du tableau de la hiérarchie ISO-639-5 sur le site |
---|
22 | * de la Library of Congress. |
---|
23 | */ |
---|
24 | define('_CODELANG_LOC_ISO639_5_HIERARCHY', 'https://www.loc.gov/standards/iso639-5/hier.php'); |
---|
25 | } |
---|
26 | |
---|
27 | |
---|
28 | $GLOBALS['iso_service'] = array( |
---|
29 | 'iso639codes' => array( |
---|
30 | 'basic_fields' => array( |
---|
31 | 'Id' => 'code_639_3', |
---|
32 | 'Part2B' => 'code_639_2b', |
---|
33 | 'Part2T' => 'code_639_2t', |
---|
34 | 'Part1' => 'code_639_1', |
---|
35 | 'Scope' => 'scope', |
---|
36 | 'Language_Type' => 'type', |
---|
37 | 'Ref_Name' => 'ref_name', |
---|
38 | 'Comment' => 'comment' |
---|
39 | ), |
---|
40 | 'delimiter' => "\t", |
---|
41 | 'extension' => '.tab' |
---|
42 | ), |
---|
43 | 'iso639names' => array( |
---|
44 | 'basic_fields' => array( |
---|
45 | 'Id' => 'code_639_3', |
---|
46 | 'Print_Name' => 'print_name', |
---|
47 | 'Inverted_Name' => 'inverted_name' |
---|
48 | ), |
---|
49 | 'delimiter' => "\t", |
---|
50 | 'extension' => '.tab' |
---|
51 | ), |
---|
52 | 'iso639macros' => array( |
---|
53 | 'basic_fields' => array( |
---|
54 | 'M_Id' => 'macro_639_3', |
---|
55 | 'I_Id' => 'code_639_3', |
---|
56 | 'I_Status' => 'status' |
---|
57 | ), |
---|
58 | 'delimiter' => "\t", |
---|
59 | 'extension' => '.tab' |
---|
60 | ), |
---|
61 | 'iso639retirements' => array( |
---|
62 | 'basic_fields' => array( |
---|
63 | 'Id' => 'code_639_3', |
---|
64 | 'Ref_Name' => 'ref_name', |
---|
65 | 'Ret_Reason' => 'ret_reason', |
---|
66 | 'Change_To' => 'change_to', |
---|
67 | 'Ret_Remedy' => 'ret_remedy', |
---|
68 | 'Effective' => 'effective_date' |
---|
69 | ), |
---|
70 | 'delimiter' => "\t", |
---|
71 | 'extension' => '.tab' |
---|
72 | ), |
---|
73 | 'iso639families' => array( |
---|
74 | 'basic_fields' => array( |
---|
75 | 'URI' => 'uri', |
---|
76 | 'code' => 'code_639_5', |
---|
77 | 'Label (English)' => 'label_en', |
---|
78 | 'Label (French)' => 'label_fr' |
---|
79 | ), |
---|
80 | 'add_fields' => array( |
---|
81 | 'sil' => array( |
---|
82 | 'Equivalent' => 'code_639_1', |
---|
83 | 'Code set' => 'code_set', |
---|
84 | 'Code sets' => 'code_set', |
---|
85 | 'Scope' => 'scope' |
---|
86 | ), |
---|
87 | 'loc' => array( |
---|
88 | 'Hierarchy' => 'hierarchy' |
---|
89 | ) |
---|
90 | ), |
---|
91 | 'delimiter' => "\t", |
---|
92 | 'extension' => '.tab' |
---|
93 | ), |
---|
94 | 'iso15924scripts' => array( |
---|
95 | 'basic_fields' => array( |
---|
96 | 'Code' => 'code_15924', |
---|
97 | 'English Name' => 'label_en', |
---|
98 | 'Nom français' => 'label_fr', |
---|
99 | 'N°' => 'code_num', |
---|
100 | 'PVA' => 'alias_en', |
---|
101 | 'Date' => 'date_ref', |
---|
102 | ), |
---|
103 | 'delimiter' => ";", |
---|
104 | 'extension' => '.txt' |
---|
105 | ), |
---|
106 | ); |
---|
107 | |
---|
108 | // ---------------------------------------------------------------------------- |
---|
109 | // ----------------- API du service ISO - Actions principales ----------------- |
---|
110 | // ---------------------------------------------------------------------------- |
---|
111 | |
---|
112 | /** |
---|
113 | * Lit le fichier .tab ou .txt contenant les enregistrements d'une des tables ISO et renvoie un tableau |
---|
114 | * prêt pour une insertion en base de données. |
---|
115 | * |
---|
116 | * @api |
---|
117 | * |
---|
118 | * @param string $table |
---|
119 | * Nom de la table ISO incluse dans la base de données spip (sans le préfixe) à savoir, |
---|
120 | * `iso639codes`, `iso639names`, `iso639macros`, `iso639retirements`, `iso639families` ou `iso15924scripts`. |
---|
121 | * @param int $sha_file |
---|
122 | * Sha calculé à partir du fichier .tab des enregistrements de la table concernée. Le sha est retourné |
---|
123 | * par la fonction afin d'être stocké par le plugin. |
---|
124 | * |
---|
125 | * @return array |
---|
126 | * Tableau des enregistrements de la table concernée prêts à une insertion en base de données. |
---|
127 | */ |
---|
128 | function iso_read_table($table, &$sha_file) { |
---|
129 | |
---|
130 | // Initialisations |
---|
131 | $records = array(); |
---|
132 | $sha_file = false; |
---|
133 | $f_complete_record = "${table}_complete_by_record"; |
---|
134 | $f_complete_table = "${table}_complete_by_table"; |
---|
135 | $file_to_spip = $GLOBALS['iso_service'][$table]['basic_fields']; |
---|
136 | $delimiter = $GLOBALS['iso_service'][$table]['delimiter']; |
---|
137 | $extension = $GLOBALS['iso_service'][$table]['extension']; |
---|
138 | |
---|
139 | if (in_array($table, array_keys($GLOBALS['iso_service']))) { |
---|
140 | // Ouvrir le fichier des enregistrements de la table spécifiée. |
---|
141 | $file = find_in_path("services/iso/${table}${extension}"); |
---|
142 | if (file_exists($file) and ($sha_file = sha1_file($file))) { |
---|
143 | // Lecture du fichier .tab ou .txt comme un fichier texte sachant que : |
---|
144 | // - le délimiteur de colonne est une tabulation ou une virgule |
---|
145 | // - pas de caractère d'enclosure |
---|
146 | $lines = file($file); |
---|
147 | if ($lines) { |
---|
148 | $headers = array(); |
---|
149 | foreach ($lines as $_number => $_line) { |
---|
150 | $values = explode($delimiter, trim($_line, "\r\n")); |
---|
151 | if ($_number == 0) { |
---|
152 | // Stockage des noms de colonnes car la première ligne contient toujours le header |
---|
153 | $headers = $values; |
---|
154 | } else { |
---|
155 | // Création de chaque enregistrement de la table |
---|
156 | $fields = array(); |
---|
157 | foreach ($headers as $_cle => $_header) { |
---|
158 | $fields[$file_to_spip[trim($_header)]] = isset($values[$_cle]) ? $values[$_cle] : ''; |
---|
159 | } |
---|
160 | // Si besoin on appelle une fonction pour chaque enregistrement afin de le compléter |
---|
161 | if (function_exists($f_complete_record)) { |
---|
162 | $fields = $f_complete_record($fields); |
---|
163 | } |
---|
164 | $records[] = $fields; |
---|
165 | } |
---|
166 | } |
---|
167 | // Si besoin on appelle une fonction pour toute la table |
---|
168 | if (function_exists($f_complete_table)) { |
---|
169 | $records = $f_complete_table($records); |
---|
170 | } |
---|
171 | } |
---|
172 | } |
---|
173 | } |
---|
174 | |
---|
175 | return $records; |
---|
176 | } |
---|
177 | |
---|
178 | |
---|
179 | // ---------------------------------------------------------------- |
---|
180 | // ------------ Fonctions internes utilisées par l'API ------------ |
---|
181 | // ---------------------------------------------------------------- |
---|
182 | |
---|
183 | function iso639families_complete_by_record($fields) { |
---|
184 | |
---|
185 | // Initialisation des champs additionnels |
---|
186 | $sil_to_spip = $GLOBALS['iso_service']['iso639families']['add_fields']['sil']; |
---|
187 | foreach($sil_to_spip as $_label => $_field) { |
---|
188 | $fields[$_field] = ''; |
---|
189 | } |
---|
190 | |
---|
191 | // On récupère la page de description de la famille sur le site SIL. |
---|
192 | include_spip('inc/distant'); |
---|
193 | $url = _CODELANG_SIL_ISO639_3_ENDPOINT . $fields['code_639_5']; |
---|
194 | $options = array('transcoder' => true); |
---|
195 | $flux = recuperer_url($url, $options); |
---|
196 | |
---|
197 | // On décrypte la page et principalement le premier tableau pour en extraire les données |
---|
198 | // additionnelles suivantes : |
---|
199 | // - scope : C(ollective) |
---|
200 | // - equivalent : éventuellement le code ISO-639-1 |
---|
201 | // - code set : ISO-639-5 et/ou ISO-639-2 |
---|
202 | include_spip('inc/filtres'); |
---|
203 | $table = extraire_balise($flux['page'], 'table'); |
---|
204 | if ($table) { |
---|
205 | // On extrait la première table de la page qui contient les données voulues |
---|
206 | $rows = extraire_balises($table, 'tr'); |
---|
207 | if ($rows) { |
---|
208 | foreach ($rows as $_row) { |
---|
209 | // Chaque ligne de la table est composée de deux colonnes, le première le libellé |
---|
210 | // et la deuxième la valeur. |
---|
211 | $columns = extraire_balises($_row, 'td'); |
---|
212 | $columns = array_map('supprimer_tags', $columns); |
---|
213 | if (count($columns) == 2) { |
---|
214 | $keys = explode(':', trim($columns[0])); |
---|
215 | $key = trim($keys[0]); |
---|
216 | $value = str_replace(' ', '', trim($columns[1])); |
---|
217 | switch ($key) { |
---|
218 | case 'Equivalent': |
---|
219 | $equivalent = explode(':', $value); |
---|
220 | $fields[$sil_to_spip[$key]] = isset($equivalent[1]) ? trim($equivalent[1]) : ''; |
---|
221 | break; |
---|
222 | case 'Code sets': |
---|
223 | case 'Code set': |
---|
224 | $fields[$sil_to_spip[$key]] = str_replace('and', ',', $value); |
---|
225 | break; |
---|
226 | case 'Scope': |
---|
227 | $fields[$sil_to_spip[$key]] = substr($value, 0, 1); |
---|
228 | break; |
---|
229 | default: |
---|
230 | break; |
---|
231 | } |
---|
232 | } |
---|
233 | } |
---|
234 | } |
---|
235 | } |
---|
236 | |
---|
237 | return $fields; |
---|
238 | } |
---|
239 | |
---|
240 | |
---|
241 | function iso639families_complete_by_table($records) { |
---|
242 | |
---|
243 | // Initialisation des champs additionnels |
---|
244 | $hierarchies =array(); |
---|
245 | $loc_to_spip = $GLOBALS['iso_service']['iso639families']['add_fields']['loc']; |
---|
246 | |
---|
247 | // On récupère la page de description de la famille sur le site SIL. |
---|
248 | include_spip('inc/distant'); |
---|
249 | $url = _CODELANG_LOC_ISO639_5_HIERARCHY; |
---|
250 | $options = array('transcoder' => true); |
---|
251 | $flux = recuperer_url($url, $options); |
---|
252 | |
---|
253 | // On décrypte la page et principalement le tableau pour en extraire la colonne hiérarchie |
---|
254 | // de chaque famille et créer la colonne parent dans la table iso639families. |
---|
255 | include_spip('inc/filtres'); |
---|
256 | $table = extraire_balise($flux['page'], 'table'); |
---|
257 | if ($table) { |
---|
258 | // On extrait la première table de la page qui contient les données voulues |
---|
259 | $rows = extraire_balises($table, 'tr'); |
---|
260 | if ($rows) { |
---|
261 | // La première ligne du tableau est celle des titres de colonnes : on la supprime. |
---|
262 | array_shift($rows); |
---|
263 | foreach ($rows as $_row) { |
---|
264 | // Chaque ligne de la table est composée de deux colonnes, le première le libellé |
---|
265 | // et la deuxième la valeur. |
---|
266 | $columns = extraire_balises($_row, 'td'); |
---|
267 | $columns = array_map('supprimer_tags', $columns); |
---|
268 | if (count($columns) >= 2) { |
---|
269 | // La première colonne contient la hiérarchie et la seconde le code alpha-3 de la famille. |
---|
270 | $code = trim($columns[1]); |
---|
271 | $hierarchies[$code] = str_replace(array(' ', ':'), array('', ','), trim($columns[0])); |
---|
272 | } |
---|
273 | } |
---|
274 | } |
---|
275 | } |
---|
276 | |
---|
277 | // On complète maintenant le tableau des enregistrements avec la colonne additionnelle hierarchy et la colonne |
---|
278 | // dérivée parent qui ne contient que le code alpha-3 de la famille parente si elle existe. |
---|
279 | foreach($records as $_cle => $_record) { |
---|
280 | $code = $_record['code_639_5']; |
---|
281 | $records[$_cle]['parent'] = ''; |
---|
282 | if (isset($hierarchies[$code])) { |
---|
283 | $records[$_cle][$loc_to_spip['Hierarchy']] = $hierarchies[$code]; |
---|
284 | // Calcul du parent : si la hierarchie ne contient qu'un code c'est qu'il n'y a pas de parent. |
---|
285 | // Sinon, le parent est le premier code qui précède le code du record. |
---|
286 | $parents = explode(',', $hierarchies[$code]); |
---|
287 | if (count($parents) > 1) { |
---|
288 | array_pop($parents); |
---|
289 | $records[$_cle]['parent'] = array_pop($parents); |
---|
290 | } |
---|
291 | } else { |
---|
292 | $records[$_cle][$loc_to_spip['Hierarchy']] = ''; |
---|
293 | } |
---|
294 | } |
---|
295 | |
---|
296 | return $records; |
---|
297 | } |
---|