source: spip-zone/_plugins_/zotspip/trunk/zotspip_fonctions.php @ 124213

Last change on this file since 124213 was 124213, checked in by Joseph Larmarange, 11 months ago

Bug fix (guillemets manquants)

File size: 16.7 KB
Line 
1<?php
2
3// Sécurité
4if (!defined("_ECRIRE_INC_VERSION")) return;
5
6// Cette balise teste si la connexion à Zotero fonctionne
7function balise_TESTER_CONNEXION_ZOTERO_dist($p) {
8                $p->code = "zotspip_tester_connexion_zotero()";
9        return $p;
10}
11
12function zotspip_tester_connexion_zotero() {
13        include_spip('inc/zotspip');
14        $feed = zotero_get('items/?format=atom&limit=1');
15        return $feed ? ' ' : '';
16}
17
18// Mets en forme une référence bibliographique
19// On peut passer le nom d'un style CSL en argument (optionel).
20// Le second argument (optionel) peut être une liste d'auteurs, tableau ou string séparée par des points-virgules, à souligner.
21function balise_REFERENCE_dist($p) {
22        $csljson = champ_sql('csljson', $p);
23        $annee = champ_sql('annee', $p);
24        $_lang = champ_sql('lang', $p);
25        $style = interprete_argument_balise(1,$p);
26        $souligne = interprete_argument_balise(2,$p);
27        $date = champ_sql('date', $p);
28        if (!$style) $style='""';
29        if (!$souligne) $souligne='array()';
30
31        $p->code = "zotspip_calculer_reference($csljson,$annee,$style,$souligne,$date,htmlentities($_lang ? $_lang : \$GLOBALS['spip_lang']))";
32        return $p;
33}
34
35function zotspip_calculer_reference($csljson,$annee,$style,$souligne,$date,$lang) {
36        include_spip('lib/citeproc-php/CiteProc');
37        include_spip('inc/config');
38        static $citeproc = array();
39        if (!$style) {
40                include_spip('inc/config');
41                $style = lire_config('zotspip/csl_defaut') ? lire_config('zotspip/csl_defaut') : 'apa';
42        }
43        $data = json_decode($csljson);
44
45        if (isset($data->issued->raw) && lire_config('zotspip/corriger_date')) { // Correction de la date de publication (si fournie brute et si option activée)
46                unset($data->issued->raw);
47                // Gestion des cas où la date est de la forme yyyy-mm ou yyyy-mm-dd
48                if (preg_match('#^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})$#',trim($date),$matches))
49                        $data->issued->{'date-parts'} = array(array($matches[1],$matches[2],$matches[3]));
50                elseif (preg_match('#^([0-9]{4})-([0-9]{1,2})$#',trim($date),$matches))
51                        $data->issued->{'date-parts'} = array(array($matches[1],$matches[2]));
52                else
53                        $data->issued->{'date-parts'} = array(array($annee));
54        }
55
56        if (!is_array($souligne)) $souligne = explode(';',$souligne);
57
58        if (count($souligne)){
59                foreach ($souligne as $aut_souligne) {
60                        if(!strpos($aut_souligne,',')) $aut_souligne .= ', ';
61                        $aut_souligne = explode(',',$aut_souligne);
62                        if (is_array($data->author))
63                                foreach ($data->author as $cle => $author)
64                                        if ($author->family == trim($aut_souligne[0]) && $author->given == trim($aut_souligne[1]))
65                                                $data->author[$cle]->family = '§§'.$data->author[$cle]->family.'§§';
66                        if (is_array($data->editor))
67                                foreach ($data->editor as $cle => $editor)
68                                        if ($editor->family == trim($aut_souligne[0]) && $editor->given == trim($aut_souligne[1]))
69                                                $data->editor[$cle]->family = '§§'.$data->editor[$cle]->family.'§§';
70                }
71        }
72
73        if (!isset($citeproc[$style])) {
74                include_spip('inc/distant');
75                $csl = spip_file_get_contents(find_in_path("csl/$style.csl"));
76                // Si le style demande n'est pas disponible, message d'erreur et se rabattre sur apa.csl
77                if (!$csl) {
78                        erreur_squelette(_T('zotspip:message_erreur_style_csl',array('style'=>$style)));
79                        $csl = spip_file_get_contents(find_in_path("csl/apa.csl"));
80                }
81                $citeproc[$style] = new citeproc($csl,$lang);
82        }
83
84        $ret = $citeproc[$style]->render($data, 'bibliography');
85        if (count($souligne))
86                $ret = preg_replace(',§§(.+)§§,U','<span style="text-decoration:underline;">$1</span>',$ret);
87
88        return $ret;
89}
90
91// Lister les styles CSL disponibles
92function balise_LISTER_CSL_dist($p) {
93        $p->code = "zotspip_lister_csl()";
94        return $p;
95}
96
97function zotspip_lister_csl(){
98        static $liste_csl = null;
99        if (is_null($liste_csl)){
100                $liste_csl = array();
101                $match = ".+[.]csl$";
102                $liste = find_all_in_path('csl/', $match);
103                if (count($liste)){
104                        foreach($liste as $fichier=>$chemin) {
105                                $style = spip_file_get_contents($chemin);
106                                $csl = substr($fichier,0,-4);
107                                if (preg_match('#\<title\>(.*)\</title\>#',$style,$matches))
108                                        $liste_csl[$csl] = $matches[1];
109                                else
110                                        $liste_csl[$csl] = $csl;
111                        }
112                }
113        }
114        return $liste_csl;
115}
116
117// Traduire le type de reference
118function zotspip_traduire_type($type) {
119        return ($type!='') ? _T('zotero:itemtypes_'.strtolower($type)) : '';
120}
121
122// Traduire le champ Zotero
123function zotspip_traduire_champ($champ) {
124        return ($champ!='') ? _T('zotero:itemfields_'.strtolower($champ)) : '';
125}
126
127// Traduire le type d'auteur
128function zotspip_traduire_createur($type) {
129        return ($type!='') ? _T('zotero:creatortypes_'.strtolower($type)) : '';
130}
131
132// Afficher l'icône du document
133// On peut optionnellement ajouter mimetype et fichier pour distinguer les icônes dans le cadre des pièces jointes
134function zotspip_icone_type($type, $mimetype=NULL, $fichier=NULL) {
135        $alt = zotspip_traduire_type($type);
136        if ($type=='attachment' && !is_null($fichier) && !$fichier) $type = 'attachment-web-link'; // Si fichier n'est pas renseigné, c'est un lien sur le web
137        if ($type=='attachment' && $fichier && $mimetype=='text/html') $type = 'attachment-snapshot';
138        if ($type=='attachment' && $fichier && $mimetype=='application/pdf') $type = 'attachment-pdf';
139        $chemin = find_in_path("images/zotero/$type.png");
140        if (!$chemin) $chemin = find_in_path("images/zotero/item.png");
141        return "<img src=\"$chemin\" height=\"16\" width=\"16\" alt=\"$alt\"/>";
142}
143
144// Renvoie un tableau HTML avec le détail de l'item
145function balise_ZITEM_DETAILS_dist($p) {
146        $json = champ_sql('json', $p);
147        $p->code = "zotspip_calculer_zitem_details($json)";
148        return $p;
149}
150
151function zotspip_calculer_zitem_details($json) {
152        $ret = '<table class="zitem_details spip">';
153        $data = json_decode($json,true);
154        if (!is_array($data)) return '';
155        foreach ($data as $champ => $valeur) {
156                if ($champ=='itemType')
157                        $ret .= "<tr><td class=\"champ\"><strong>".zotspip_traduire_champ($champ)."</strong></td><td class=\"valeur\">".zotspip_traduire_type($valeur)."</td></tr>";
158                elseif ($champ=='creators')
159                        foreach ($valeur as $creator)
160                                $ret .= "<tr><td class=\"champ\"><strong>".zotspip_traduire_createur($creator['creatorType'])."</strong></td><td class=\"valeur\">".(isset($creator['name'])?$creator['name']:($creator['lastName'].(isset($creator['firstName'])?', '.$creator['firstName']:'')))."</td></tr>";
161                elseif ($champ=='tags' && count($valeur)>0) {
162                        $tags = array();
163                        foreach ($valeur as $tag)
164                                $tags[] = $tag['tag'];
165                        $tags = implode(' &middot; ',$tags);
166                        $ret .= "<tr><td class=\"champ\"><strong>"._T('zotero:itemfields_tags')."</strong></td><td class=\"valeur\">$tags</td></tr>";
167                }
168                elseif ($champ=='mimeType')
169                        $ret .= "<tr><td class=\"champ\"><strong>MIME</strong></td><td class=\"valeur\">$valeur</td></tr>";
170                elseif ($champ=='url')
171                        $ret .= "<tr><td class=\"champ\"><strong>".zotspip_traduire_champ($champ)."</strong></td><td class=\"valeur\"><a href=\"$valeur\">$valeur</a></td></tr>";
172                elseif ($valeur)
173                        $ret .= "<tr><td class=\"champ\"><strong>".zotspip_traduire_champ($champ)."</strong></td><td class=\"valeur\">$valeur</td></tr>";
174        }
175        $ret .= '</table>';
176        return $ret;
177}
178
179// Exporte les items dans le format demandé
180function zotspip_export ($id, $format) {
181        if (is_array($id)) $id = implode(',',$id);
182        include_spip('inc/zotspip');
183        return zotero_get("items/?itemKey=$id&format=$format");
184}
185
186// Renvoie le content-type correspondant à un format d'export
187function zotspip_content_type ($format) {
188        switch ($format) {
189                case 'bibtex':
190                        $ctype = "application/x-bibtex";
191                        break;
192                case 'mods':
193                        $ctype = "application/mods+xml";
194                        break;
195                case 'refer':
196                        $ctype = "application/x-research-info-systems" ;
197                        break;
198                case 'rdf_bibliontology':
199                case 'rdf_dc':
200                case 'rdf_zotero':
201                        $ctype = "application/rdf+xml";
202                        break;
203                case 'ris':
204                        $ctype = "application/x-research-info-systems";
205                        break;
206                case 'wikipedia':
207                        $ctype = "text/x-wiki";
208                        break;
209                default:
210                        $ctype = '';
211                        break;
212        }
213        return ($ctype) ? 'Content-Type: '.$ctype : '';
214}
215
216// Indique le nom du fichier à télécharger
217function zotspip_content_disposition ($format) {
218        switch ($format) {
219                case 'bibtex':
220                        $ext = 'bib';
221                        break;
222                case 'mods':
223                        $ext = 'xml';
224                        break;
225                case 'refer':
226                case 'wikipedia':
227                        $ext = 'txt';
228                        break;
229                case 'rdf_bibliontology':
230                case 'rdf_dc':
231                case 'rdf_zotero':
232                        $ext = 'rdf';
233                        break;
234                case 'ris':
235                        $ext = 'ris';
236                        break;
237                default:
238                        $ext = '';
239                        break;
240        }
241        return ($ext) ? 'Content-Disposition: attachment; filename=export.'.$ext : '';
242}
243
244// Récupère un fichier distant
245function zotspip_recuperer_fichier($fichier, $titre, $id_zitem, $mimetype, $json) {
246        $snapshot = (substr($fichier,-4) == 'view'); // Il s'agit d'un snapshot
247        if ($snapshot) {
248                $url_snapshot = substr($fichier,0,-5).'?key='.lire_config('zotspip/api_key');
249                $json = json_decode($json, true);
250                $filename = $json['filename'];
251        }
252        $url_distante = $fichier.'?key='.lire_config('zotspip/api_key');
253        $titre = translitteration($titre);
254        // Recuperer la bonne extension de fichier en fonction du type mime
255        include_spip('base/abstract_sql');
256        $ext = sql_getfetsel('extension','spip_types_documents','mime_type='.sql_quote($mimetype));
257        // On nettoie et on ajoute l'extension
258        if ($ext) {
259                if (substr($titre,-1*(strlen($ext)+1))=='.'.$ext) $titre = substr($titre,0,-1*(strlen($ext)+1));
260                $titre = preg_replace(',[[:punct:][:space:]]+,u', ' ', $titre);
261                $titre = preg_replace(',\.([^.]+)$,', '', $titre);
262                $titre .= '.'.$ext;
263        }
264        $url_locale = _DIR_VAR."cache-zotspip/$id_zitem/$titre";
265
266        if (!@file_exists($url_locale)) {
267                include_spip('inc/distant');
268                include_spip('inc/flock');
269                sous_repertoire(_DIR_VAR."cache-zotspip");
270                sous_repertoire(_DIR_VAR."cache-zotspip/$id_zitem");
271                ecrire_fichier($url_locale,recuperer_page($url_distante,false,false,_COPIE_LOCALE_MAX_SIZE));
272                if ($snapshot) {
273                        // Dans ce cas, il faut télécharger le zip, le dezipper et renommer les fichiers en appliquant base64_decode().
274                        sous_repertoire(_DIR_CACHE."tmp-zotspip");
275                        ecrire_fichier(_DIR_CACHE."tmp-zotspip/$id_zitem.zip",recuperer_page($url_snapshot,false,false,_COPIE_LOCALE_MAX_SIZE));
276                        include_spip('inc/pclzip');
277                        $zip = new PclZip(_DIR_CACHE."tmp-zotspip/$id_zitem.zip");
278                        $zip->extract(PCLZIP_OPT_PATH,_DIR_VAR."cache-zotspip/$id_zitem",PCLZIP_CB_PRE_EXTRACT, 'zotspip_decode_64_nom');
279                        supprimer_fichier(_DIR_CACHE."tmp-zotspip/$id_zitem.zip");
280                }
281        }
282        include_spip('inc/headers');
283        redirige_par_entete($url_locale);
284}
285
286// Utiliser pour renommer correctement les fichiers du snapshot
287function zotspip_decode_64_nom($p_event, &$p_header){
288        $info = pathinfo($p_header['filename']);
289        $p_header['filename'] = $info['dirname'].'/'.base64_decode(substr($info['basename'],0,-5));
290        return 1;
291}
292
293
294// Récupérer les références les plus récentes
295// La variable d'environnement depuis peut être de la forme depuis=2008, depuis=2ans ou depuis=1an
296function critere_zotsip_depuis($idb, &$boucles, $crit) {
297        $boucle = &$boucles[$idb];
298        $table = $boucle->id_table;
299        $boucle->where[] = "zotspip_calcul_depuis(\$Pile[0]['depuis'],'$table')";
300}
301function zotspip_calcul_depuis($depuis,$table) {
302        $annee = false;
303        if (is_numeric($depuis)) $annee = intval($depuis);
304        elseif (substr($depuis,-2)=='an' && is_numeric(substr($depuis,0,-2))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-2)); // L'année en cours compte pour un
305        elseif (substr($depuis,-3)=='ans' && is_numeric(substr($depuis,0,-3))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-3));
306        elseif (substr($depuis,-1)=='a' && is_numeric(substr($depuis,0,-1))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-1));
307        elseif (substr($depuis,-5)=='years' && is_numeric(substr($depuis,0,-5))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-5)); // Prise en charge de l'anglais
308        elseif (substr($depuis,-4)=='year' && is_numeric(substr($depuis,0,-4))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-4));
309        elseif (substr($depuis,-1)=='y' && is_numeric(substr($depuis,0,-1))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-1));
310        elseif (substr($depuis,-4)=='años' && is_numeric(substr($depuis,0,-4))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-4)); // Prise en charge et de l'espagnol
311        elseif (substr($depuis,-3)=='año' && is_numeric(substr($depuis,0,-3))) $annee = 1 + intval(date('Y')) - intval(substr($depuis,0,-3));
312        if ($annee) return array('>=',"$table.annee",$annee);
313        else return array();
314}
315
316// Renvoie le schéma de données Zotero
317function schema_zotero($entree = '') {
318        static $schema = NULL;
319        if (is_null($chema)) {
320                lire_fichier_securise(_DIR_TMP . 'schema_zotero.php', $schema);
321                $schema = @unserialize($schema);
322        }
323        if (!$entree)
324                return $schema;
325        else
326                return $schema[$entree];
327}
328
329function balise_SCHEMA_ZOTERO_dist($p) {
330        $entree = interprete_argument_balise(1,$p);
331        if (!$entree) $entree='""';
332        $p->code = "schema_zotero($entree)";
333        return $p;
334}
335
336// Permet de trier la liste des types de références à partir de leur traduction
337// Utilisation : [(#SCHEMA_ZOTERO{itemTypes}|zotspip_trier_itemTypes})]
338function zotspip_trier_itemTypes($itemTypes,$inclure_note=false) {
339        $l = array();
340        foreach ($itemTypes as $itemType)
341                if($inclure_note || $itemType != 'note')
342                        $l[$itemType] = zotspip_traduire_type($itemType);
343        asort($l);
344        return array_keys($l);
345}
346
347// Fournit une liste complète de l'ensemble des types d'auteurs (en fusionnant les listes de chaque itemType)
348// Utilisation : [(#SCHEMA_ZOTERO{creatorTypes}|zotspip_liste_creatorTypes_complete)]
349function zotspip_liste_creatorTypes_complete($creatorTypes) {
350        $retour = array();
351        foreach ($creatorTypes as $creatorType)
352                $retour = array_merge($retour,array_diff($creatorType,$retour));
353        return $retour;
354}
355
356// Renvoie l'URL de visualisation d'un item sur zotero.org
357function voir_sur_zotero($id_zitem){
358        if(lire_config('zotspip/type_librairie')=='user')
359                return "https://www.zotero.org/".lire_config('zotspip/username')."/items/itemKey/$id_zitem";
360        else
361                return "https://www.zotero.org/groups/".lire_config('zotspip/username')."/items/itemKey/$id_zitem";
362}
363
364// Renvoie l'URL de modification d'un item sur zotero.org
365function modifier_sur_zotero($id_zitem){
366        if(lire_config('zotspip/type_librairie')=='user')
367                return "https://www.zotero.org/".lire_config('zotspip/username')."/items/itemKey/$id_zitem/mode/edit";
368        else
369                return "https://www.zotero.org/groups/".lire_config('zotspip/username')."/items/itemKey/$id_zitem/mode/edit";
370}
371
372// Fonction renvoyant le tableau adequat pour la configuration de l'ordre des types de documents
373function zotspip_configurer_ordre_types($ordre) {
374        if (!is_array($ordre)) $ordre=array();
375        $ordre = array_flip($ordre);
376        // Il faut completer par rapport au schema Zotero (au cas ou le schema change)
377        $zotero = schema_zotero('itemTypes');
378        $zotero[]='attachment'; // Ajouter les pieces jointes non presentes dans le schema
379        $ordre = array_merge($ordre,array_flip($zotero));
380        // Ajout des chaines de langue
381        foreach ($ordre as $cle => $val)
382                $ordre[$cle] = zotspip_traduire_type($cle);
383        return $ordre;
384}
385
386// Le critere qui permet le tri par type (selon l'ordre defini)
387function critere_par_type_zotero($idb, &$boucles, $crit) {
388        $boucle = &$boucles[$idb];
389        $id_table = $boucle->id_table;
390        include_spip('inc/config');
391        $config = lire_config('zotspip/ordre_types');
392        if (is_array($config) && count($config))
393                $boucle->order[] = "\"FIELD($id_table.type_ref,'".implode("','",$config)."')\"";
394        else
395                $boucle->order[] = "'$id_table.type_ref'";
396}
397
398// Renvoie le premier auteur a partir du champs auteurs de la table zitems
399function zotspip_premier_auteur($auteurs) {
400        $auteurs = explode(', ',$auteurs);
401        return $auteurs[0];
402}
403
404// Renvoie le tableau des id passes à [ref=XXX]
405function zotspip_ids_ref($ids) {
406        $ids = explode(',',$ids);
407        foreach ($ids as $cle => $id) $ids[$cle] = trim($id); // (on supprime les espaces inutiles)
408        foreach ($ids as $cle => $id) {
409                if ($p=strpos($id,'@'))
410                        $ids[$cle] = substr($id,0,$p); // on ne garde que la partie avant le @
411        }
412        return $ids;
413}
414
415// Renvoie le tableau des positions/suffixes passés à [ref=XXX]
416function zotspip_suffixes_ref($ids) {
417        $ret = array();
418        $ids = explode(',',$ids);
419        foreach ($ids as $cle => $id) $ids[$cle] = trim($id); // (on supprime les espaces inutiles)
420        foreach ($ids as $cle => $id) {
421                if ($p=strpos($id,'@')) {
422                        $id_zitem = substr($id,0,$p); // id_zitem est avant le @
423                        $ret[$id_zitem] = substr($id,$p+1); // suffixe apres le @
424                        }
425        }
426        return $ret;
427}
428
429// Utilise pour les [ref=XXX] les div ne sont pas pertinents dans une note
430function zotspip_div_en_span($texte) {
431        return preg_replace('#div#U','span',$texte);
432}
433
434
435?>
Note: See TracBrowser for help on using the repository browser.