50243afa7d696f13cafab11b3714dec65370ad1e
[lhc/web/www.git] / www / plugins-dist / medias / formulaires / joindre_document.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2016 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 /**
14 * Gestion du formulaire de téléversement de documents
15 *
16 * @package SPIP\Medias\Formulaires
17 */
18 if (!defined('_ECRIRE_INC_VERSION')) {
19 return;
20 }
21
22 /**
23 * Déterminer le mode d'upload si la valeur au chargement du formulaire est "auto"
24 *
25 * @param string $mode
26 * Le mode passé au formulaire
27 * @param int|string $id_document
28 * L'identifiant numérique du document à remplacer ou "new" par défaut
29 * @param string $objet
30 * Le type d'objet sur lequel ajouter le document
31 * @return string $mode
32 * Le mode définitif
33 */
34 function joindre_determiner_mode($mode, $id_document, $objet) {
35 if ($mode == 'auto') {
36 if (intval($id_document)) {
37 $mode = sql_getfetsel('mode', 'spip_documents', 'id_document=' . intval($id_document));
38 }
39 if (!in_array($mode, array('choix', 'document', 'image'))) {
40 $mode = 'choix';
41 if ($objet
42 and !in_array(table_objet_sql($objet), explode(',', $GLOBALS['meta']['documents_objets']))) {
43 $mode = 'image';
44 }
45 }
46 }
47
48 return $mode;
49 }
50
51 /**
52 * Chargement du formulaire
53 *
54 * @param int|string $id_document
55 * L'identidiant numérique du document s'il est à remplacer, sinon "new"
56 * @param int $id_objet
57 * L'identifiant numérique de l'objet sur lequel on ajoute le document
58 * @param string $objet
59 * Le type de l'objet sur lequel on ajoute le document
60 * @param string $mode
61 * Le mode du document (auto,choix,document,image,vignette...), par défaut auto
62 * @param string $galerie
63 * Passer optionnellement une galerie jointe au form, plus utilise nativement,
64 * on prefere la mise a jour apres upload par ajaxReload('documents')
65 * @param bool|string $proposer_media
66 * Doit on afficher la médiathèque ? par défaut oui
67 * Valeurs possibles si string : false,'non','no'.
68 * @param bool|string $proposer_ftp
69 * Doit on afficher le ftp ? par défaut oui
70 * Valeurs possibles si string : false,'non','no'.
71 * @return array $valeurs
72 * Les valeurs chargées dans le formulaire
73 */
74 function formulaires_joindre_document_charger_dist(
75 $id_document = 'new',
76 $id_objet = 0,
77 $objet = '',
78 $mode = 'auto',
79 $galerie = false,
80 $proposer_media = true,
81 $proposer_ftp = true
82 ) {
83 $valeurs = array();
84 $mode = joindre_determiner_mode($mode, $id_document, $objet);
85
86
87 $valeurs['id'] = $id_document;
88 $valeurs['_mode'] = $mode;
89
90 $valeurs['url'] = 'http://';
91 $valeurs['fichier_upload'] = $valeurs['_options_upload_ftp'] = $valeurs['_dir_upload_ftp'] = '';
92 $valeurs['joindre_upload'] = $valeurs['joindre_distant'] =
93 $valeurs['joindre_ftp'] = $valeurs['joindre_mediatheque'] = '';
94
95 // gérer le focus de la méthode d'upload lorsque le formulaire est envoyé
96 $valeurs['methode_focus'] = _request('methode_focus');
97
98 $valeurs['editable'] = ' ';
99 if (intval($id_document)) {
100 $valeurs['editable'] = autoriser('modifier', 'document', $id_document) ? ' ' : '';
101 }
102
103 $valeurs['proposer_media'] = is_string($proposer_media) ?
104 (preg_match('/^(false|non|no)$/i', $proposer_media) ? false : true) : $proposer_media;
105 $valeurs['proposer_ftp'] = is_string($proposer_ftp) ?
106 (preg_match('/^(false|non|no)$/i', $proposer_ftp) ? false : true) : $proposer_ftp;
107
108 # regarder si un choix d'upload FTP est vraiment possible
109 if (
110 $valeurs['proposer_ftp']
111 and test_espace_prive() # ??
112 and ($mode != 'image') and ($mode != 'vignette') # si c'est pour un document
113 //AND !$vignette_de_doc
114 // pas pour une vignette (NB: la ligne precedente suffit, mais si on la supprime il faut conserver ce test-ci)
115 and $GLOBALS['flag_upload']
116 ) {
117 include_spip('inc/documents');
118 if ($dir = determine_upload('documents')) {
119 // quels sont les docs accessibles en ftp ?
120 $valeurs['_options_upload_ftp'] = joindre_options_upload_ftp($dir, $mode);
121 // s'il n'y en a pas, on affiche un message d'aide
122 // en mode document, mais pas en mode image
123 if ($valeurs['_options_upload_ftp'] or ($mode == 'document' or $mode == 'choix')) {
124 $valeurs['_dir_upload_ftp'] = '<b>' . joli_repertoire($dir) . '</b>';
125 }
126 }
127 }
128 // On ne propose le FTP que si on a des choses a afficher
129 $valeurs['proposer_ftp'] = ($valeurs['_options_upload_ftp'] or $valeurs['_dir_upload_ftp']);
130
131 if ($galerie) {
132 # passer optionnellement une galerie jointe au form
133 # plus utilise nativement, on prefere la mise a jour
134 # apres upload par ajaxReload('documents')
135 $valeurs['_galerie'] = $galerie;
136 }
137 if ($objet and $id_objet) {
138 $valeurs['id_objet'] = $id_objet;
139 $valeurs['objet'] = $objet;
140 $valeurs['refdoc_joindre'] = '';
141 if ($valeurs['editable']) {
142 include_spip('inc/autoriser');
143 $valeurs['editable'] = autoriser('joindredocument', $objet, $id_objet) ? ' ' : '';
144 }
145 }
146
147 return $valeurs;
148 }
149
150 /**
151 * Vérification du formulaire
152 *
153 * @param int|string $id_document
154 * L'identidiant numérique du document s'il est à remplacer, sinon "new"
155 * @param int $id_objet
156 * L'identifiant numérique de l'objet sur lequel on ajoute le document
157 * @param string $objet
158 * Le type de l'objet sur lequel on ajoute le document
159 * @param string $mode
160 * Le mode du document (auto,choix,document,image,vignette...), par défaut auto
161 * @param string $galerie
162 * Passer optionnellement une galerie jointe au form, plus utilise nativement,
163 * on prefere la mise a jour apres upload par ajaxReload('documents')
164 * @param bool|string $proposer_media
165 * Doit on afficher la médiathèque ? par défaut oui
166 * Valeurs possibles si string : false,'non','no'.
167 * @param bool|string $proposer_ftp
168 * Doit on afficher le ftp ? par défaut oui
169 * Valeurs possibles si string : false,'non','no'.
170 * @return array $erreurs
171 * Les erreurs éventuelles dans un tableau
172 */
173 function formulaires_joindre_document_verifier_dist(
174 $id_document = 'new',
175 $id_objet = 0,
176 $objet = '',
177 $mode = 'auto',
178 $galerie = false,
179 $proposer_media = true,
180 $proposer_ftp = true
181 ) {
182 include_spip('inc/joindre_document');
183
184 $erreurs = array();
185 // on joint un document deja dans le site
186 if (_request('joindre_mediatheque')) {
187 $refdoc_joindre = intval(preg_replace(',^(doc|document|img),', '', _request('refdoc_joindre')));
188 if (!sql_getfetsel('id_document', 'spip_documents', 'id_document=' . intval($refdoc_joindre))) {
189 $erreurs['message_erreur'] = _T('medias:erreur_aucun_document');
190 }
191 } // sinon c'est un upload
192 else {
193 $files = joindre_trouver_fichier_envoye();
194 if (is_string($files)) {
195 $erreurs['message_erreur'] = $files;
196 } elseif (is_array($files)) {
197 // erreur si on a pas trouve de fichier
198 if (!count($files)) {
199 $erreurs['message_erreur'] = _T('medias:erreur_aucun_fichier');
200 } else {
201 // regarder si on a eu une erreur sur l'upload d'un fichier
202 foreach ($files as $file) {
203 if (isset($file['error'])
204 and $test = joindre_upload_error($file['error'])
205 ) {
206 if (is_string($test)) {
207 $erreurs['message_erreur'] = $test;
208 } else {
209 $erreurs['message_erreur'] = _T('medias:erreur_aucun_fichier');
210 }
211 }
212 }
213
214 // si ce n'est pas deja un post de zip confirme
215 // regarder si il faut lister le contenu du zip et le presenter
216 if (!count($erreurs)
217 and !_request('joindre_zip')
218 and $contenu_zip = joindre_verifier_zip($files)
219 ) {
220 list($fichiers, $erreurs, $tmp_zip) = $contenu_zip;
221 if ($fichiers) {
222 // on passe le md5 du fichier uniquement, on le retrouvera dans zip_to_clean de la session
223 $token_zip = md5($tmp_zip);
224 $erreurs['message_erreur'] = '';
225 $erreurs['lister_contenu_archive'] = recuperer_fond(
226 'formulaires/inc-lister_archive_jointe',
227 array(
228 'chemin_zip' => $token_zip,
229 'liste_fichiers_zip' => $fichiers,
230 'erreurs_fichier_zip' => $erreurs
231 )
232 );
233 } else {
234 $erreurs['message_erreur'] = _T('medias:erreur_aucun_fichier');
235 }
236 }
237 }
238 }
239
240 if (count($erreurs) and defined('_TMP_DIR')) {
241 effacer_repertoire_temporaire(_TMP_DIR);
242 }
243 }
244
245 return $erreurs;
246 }
247
248 /**
249 * Traitement du formulaire
250 *
251 * @param int|string $id_document
252 * L'identidiant numérique du document s'il est à remplacer, sinon "new"
253 * @param int $id_objet
254 * L'identifiant numérique de l'objet sur lequel on ajoute le document
255 * @param string $objet
256 * Le type de l'objet sur lequel on ajoute le document
257 * @param string $mode
258 * Le mode du document (auto,choix,document,image,vignette...), par défaut auto
259 * @param string $galerie
260 * Passer optionnellement une galerie jointe au form, plus utilise nativement,
261 * on prefere la mise a jour apres upload par ajaxReload('documents')
262 * @param bool|string $proposer_media
263 * Doit on afficher la médiathèque ? par défaut oui
264 * Valeurs possibles si string : false,'non','no'.
265 * @param bool|string $proposer_ftp
266 * Doit on afficher le ftp ? par défaut oui
267 * Valeurs possibles si string : false,'non','no'.
268 * @return array $res
269 * Le tableau renvoyé par les CVT avec le message et editable
270 */
271 function formulaires_joindre_document_traiter_dist(
272 $id_document = 'new',
273 $id_objet = 0,
274 $objet = '',
275 $mode = 'auto',
276 $galerie = false,
277 $proposer_media = true,
278 $proposer_ftp = true
279 ) {
280 $res = array('editable' => true);
281 $ancre = '';
282 // on joint un document deja dans le site
283 if (_request('joindre_mediatheque')) {
284 $sel = array();
285 $refdoc_joindre = _request('refdoc_joindre');
286 $refdoc_joindre = strtr($refdoc_joindre, ';,', ' ');
287 $refdoc_joindre = preg_replace(',\b(doc|document|img),', '', $refdoc_joindre);
288 // expliciter les intervales xxx-yyy
289 while (preg_match(",\b(\d+)-(\d+)\b,", $refdoc_joindre, $m)) {
290 $refdoc_joindre = str_replace($m[0], implode(' ', range($m[1], $m[2])), $refdoc_joindre);
291 }
292 $refdoc_joindre = explode(' ', $refdoc_joindre);
293 include_spip('action/editer_document');
294 foreach ($refdoc_joindre as $j) {
295 if ($j = intval(preg_replace(',^(doc|document|img),', '', $j))) {
296 // lier le parent en plus
297 $champs = array('ajout_parents' => array("$objet|$id_objet"));
298 document_modifier($j, $champs);
299 if (!$ancre) {
300 $ancre = $j;
301 }
302 $sel[] = $j;
303 $res['message_ok'] = _T('medias:document_attache_succes');
304 }
305 }
306 if ($sel) {
307 $res['message_ok'] = singulier_ou_pluriel(
308 count($sel),
309 'medias:document_attache_succes',
310 'medias:nb_documents_attache_succes'
311 );
312 }
313 set_request('refdoc_joindre', ''); // vider la saisie
314 } // sinon c'est un upload
315 else {
316 $ajouter_documents = charger_fonction('ajouter_documents', 'action');
317
318 $mode = joindre_determiner_mode($mode, $id_document, $objet);
319 include_spip('inc/joindre_document');
320 $files = joindre_trouver_fichier_envoye();
321
322 $nouveaux_doc = $ajouter_documents($id_document, $files, $objet, $id_objet, $mode);
323
324 if (defined('_TMP_ZIP')) {
325 unlink(_TMP_ZIP);
326 }
327 if (defined('_TMP_DIR')) {
328 effacer_repertoire_temporaire(_TMP_DIR);
329 }
330
331 // checker les erreurs eventuelles
332 $messages_erreur = array();
333 $sel = array();
334 foreach ($nouveaux_doc as $doc) {
335 if (!is_numeric($doc)) {
336 $messages_erreur[] = $doc;
337 } // cas qui devrait etre traite en amont
338 elseif (!$doc) {
339 $messages_erreur[] = _T('medias:erreur_insertion_document_base', array('fichier' => '<em>???</em>'));
340 } else {
341 if (!$ancre) {
342 $ancre = $doc;
343 }
344 $sel[] = $doc;
345 }
346 }
347 if (count($messages_erreur)) {
348 $res['message_erreur'] = implode('<br />', $messages_erreur);
349 }
350 if ($sel) {
351 $res['message_ok'] = singulier_ou_pluriel(
352 count($sel),
353 'medias:document_installe_succes',
354 'medias:nb_documents_installe_succes'
355 );
356 }
357 if ($ancre) {
358 $res['redirect'] = "#doc$ancre";
359 }
360 }
361 if (count($sel) or isset($res['message_ok'])) {
362 $callback = '';
363 if ($ancre) {
364 $callback .= "jQuery('#doc$ancre a.editbox').eq(0).focus();";
365 }
366 if (count($sel)) {
367 // passer les ids document selectionnes aux pipelines
368 $res['ids'] = $sel;
369
370 $sel = '#doc' . implode(',#doc', $sel);
371 $callback .= "jQuery('$sel').animateAppend();";
372 }
373 $js = "if (window.jQuery) jQuery(function(){ajaxReload('documents',{callback:function(){ $callback }});});";
374 $js = "<script type='text/javascript'>$js</script>";
375 if (isset($res['message_erreur'])) {
376 $res['message_erreur'] .= $js;
377 } else {
378 $res['message_ok'] .= $js;
379 }
380 }
381
382 return $res;
383 }
384
385 /**
386 * Retourner le contenu du select HTML d'utilisation de fichiers envoyes par le serveur
387 *
388 * @param string $dir
389 * Le répertoire de recherche des documents
390 * @param string $mode
391 * Le mode d'ajout de document
392 * @return string $texte
393 * Le contenu HTML du selecteur de documents
394 */
395 function joindre_options_upload_ftp($dir, $mode = 'document') {
396 $fichiers = preg_files($dir);
397 $exts = $dirs = $texte_upload = array();
398
399 // en mode "charger une image", ne proposer que les inclus
400 $inclus = ($mode == 'image' or $mode == 'vignette')
401 ? " AND inclus='image'"
402 : '';
403
404 foreach ($fichiers as $f) {
405 $f = preg_replace(",^$dir,", '', $f);
406 if (preg_match(',\.([^.]+)$,', $f, $match)) {
407 $ext = strtolower($match[1]);
408 if (!isset($exts[$ext])) {
409 include_spip('action/ajouter_documents');
410 $ext = corriger_extension($ext);
411 if (sql_fetsel('extension', 'spip_types_documents', $a = "extension='$ext'" . $inclus)) {
412 $exts[$ext] = 'oui';
413 } else {
414 $exts[$ext] = 'non';
415 }
416 }
417
418 $k = 2 * substr_count($f, '/');
419 $n = strrpos($f, '/');
420 if ($n === false) {
421 $lefichier = $f;
422 } else {
423 $lefichier = substr($f, $n + 1, strlen($f));
424 $ledossier = substr($f, 0, $n);
425 if (!in_array($ledossier, $dirs)) {
426 $texte_upload[] = "\n<option value=\"$ledossier\">"
427 . str_repeat('&nbsp;', $k)
428 . _T('medias:tout_dossier_upload', array('upload' => $ledossier))
429 . '</option>';
430 $dirs[] = $ledossier;
431 }
432 }
433
434 if ($exts[$ext] == 'oui') {
435 $texte_upload[] = "\n<option value=\"$f\">"
436 . str_repeat('&nbsp;', $k + 2)
437 . $lefichier
438 . '</option>';
439 }
440 }
441 }
442
443 $texte = join('', $texte_upload);
444 if (count($texte_upload) > 1) {
445 $texte = "\n<option value=\"/\" style='font-weight: bold;'>"
446 . _T('medias:info_installer_tous_documents')
447 . '</option>' . $texte;
448 }
449
450 return $texte;
451 }
452
453
454 /**
455 * Lister les fichiers contenus dans un zip
456 *
457 * @param array $files
458 * La liste des fichiers
459 * @return string $res
460 * La liste HTML des fichiers <li>...</li>
461 */
462 function joindre_liste_contenu_tailles_archive($files) {
463 include_spip('inc/charsets'); # pour le nom de fichier
464
465 $res = '';
466 if (is_array($files)) {
467 foreach ($files as $nom => $file) {
468 $nom = translitteration($nom);
469 $date = date_interface(date('Y-m-d H:i:s', $file['mtime']));
470 $taille = taille_en_octets($file['size']);
471 $res .= '<li title="' . attribut_html($nom) . "\"><b>$nom</b> &ndash; $taille<br />&nbsp; $date</li>\n";
472 }
473 }
474
475 return $res;
476 }
477
478 /**
479 * Lister les erreurs dans une archive jointe
480 * Utilisé formulaires/inc-lister_archive_jointe.html
481 *
482 * @param array $erreurs
483 * La liste des erreurs
484 * @return string $res
485 * Le code HTML des erreurs
486 */
487 function joindre_liste_erreurs_to_li($erreurs) {
488 if (count($erreurs) == 1) {
489 return '<p>' . reset($erreurs) . '</p>';
490 }
491
492 $res = implode('</li><li>', $erreurs);
493 if (strlen($res)) {
494 $res = "<li>$res</li></ul>";
495 }
496 if (count($erreurs) > 4) {
497 $res = "<p style='cursor:pointer;' onclick='jQuery(this).siblings(\"ul\").toggle();return false;'>" . _T(
498 'medias:erreurs_voir',
499 array('nb' => count($erreurs))
500 ) . '</p><ul class="spip none-js">' . $res . '</ul>';
501 } else {
502 $res = "<ul class=\"spip\">$res</ul>";
503 }
504
505 return $res;
506 }