X-Git-Url: http://git.cyclocoop.org/?p=velocampus%2Fweb%2Fwww.git;a=blobdiff_plain;f=www%2Fecrire%2Finc%2Fediter.php;fp=www%2Fecrire%2Finc%2Fediter.php;h=ecfc1dd193e1be48de445264e3b5615e982dacab;hp=0000000000000000000000000000000000000000;hb=80b4d3e85f78d402ed2e73f8f5d1bf4c19962eed;hpb=aaf970bf4cdaf76689ecc10609048e18d073820c diff --git a/www/ecrire/inc/editer.php b/www/ecrire/inc/editer.php new file mode 100644 index 0000000..ecfc1dd --- /dev/null +++ b/www/ecrire/inc/editer.php @@ -0,0 +1,408 @@ +$conflit){ + $erreurs[$champ] .= _T("alerte_modif_info_concourante")."
"; + } + } + } + foreach($oblis as $obli){ + if (!_request($obli)) + $erreurs[$obli] .= _T("info_obligatoire"); + } + return $erreurs; +} + +// http://doc.spip.org/@formulaires_editer_objet_charger +function formulaires_editer_objet_charger($type, $id='new', $id_parent=0, $lier_trad=0, $retour='', $config_fonc='articles_edit_config', $row=array(), $hidden=''){ + $table_objet = table_objet($type); + $table_objet_sql = table_objet_sql($type); + $id_table_objet = id_table_objet($type); + $new = !is_numeric($id); + + // Appel direct dans un squelette + if (!$row) { + if (!$new OR $lier_trad) { + if ($select = charger_fonction($type."_select",'inc',true)) + $row = $select($id, $id_parent, $lier_trad); + else $row = sql_fetsel('*',$table_objet_sql,$id_table_objet."=".intval($id)); + if (!$new) + $md5 = controles_md5($row); + } + if (!$row) { + $trouver_table = charger_fonction('trouver_table','base'); + if ($desc = $trouver_table($table_objet)) + foreach($desc['field'] as $k=>$v) $row[$k]=''; + } + } + // Gaffe: sans ceci, on ecrase systematiquement l'article d'origine + // (et donc: pas de lien de traduction) + $id = ($new OR $lier_trad) + ? 'oui' + : $row[$id_table_objet]; + $row[$id_table_objet] = $id; + + $contexte = $row; + if ($id_parent && (!isset($contexte['id_parent']) OR $new)) + $contexte['id_parent']=$id_parent; + + if ($config_fonc) + $contexte['config'] = $config = $config_fonc($contexte); + $att_text = " class='textarea' " + . " rows='" + . ($config['lignes'] +15) + . "' cols='40'"; + list($contexte['texte'],$contexte['_texte_trop_long']) = editer_texte_recolle($contexte['texte'],$att_text); + + // on veut conserver la langue de l'interface ; + // on passe cette donnee sous un autre nom, au cas ou le squelette + // voudrait l'exploiter + if (isset($contexte['lang'])) { + $contexte['langue'] = $contexte['lang']; + unset($contexte['lang']); + } + + $contexte['_hidden'] = "\n" . + (!$lier_trad ? '' : + ("\n" . + "\n")) + . $hidden + . $md5; + + + if (isset($contexte['extra'])) + $contexte['extra'] = unserialize($contexte['extra']); + // preciser que le formulaire doit passer dans un pipeline + $contexte['_pipeline'] = array('editer_contenu_objet',array('type'=>$type,'id'=>$id)); + + // preciser que le formulaire doit etre securise auteur/action + // n'est plus utile lorsque l'action accepte l'id en argument direct + // on le garde pour compat + $contexte['_action'] = array("editer_$type",$id); + + return $contexte; +} + +// +// Gestion des textes trop longs (limitation brouteurs) +// utile pour les textes > 32ko + +// http://doc.spip.org/@coupe_trop_long +function coupe_trop_long($texte){ + $aider = charger_fonction('aider', 'inc'); + if (strlen($texte) > 28*1024) { + $texte = str_replace("\r\n","\n",$texte); + $pos = strpos($texte, "\n\n", 28*1024); // coupe para > 28 ko + if ($pos > 0 and $pos < 32 * 1024) { + $debut = substr($texte, 0, $pos)."\n\n\n"; + $suite = substr($texte, $pos + 2); + } else { + $pos = strpos($texte, " ", 28*1024); // sinon coupe espace + if (!($pos > 0 and $pos < 32 * 1024)) { + $pos = 28*1024; // au pire (pas d'espace trouv'e) + $decalage = 0; // si y'a pas d'espace, il ne faut pas perdre le caract`ere + } else { + $decalage = 1; + } + $debut = substr($texte,0,$pos + $decalage); // Il faut conserver l'espace s'il y en a un + $suite = substr($texte,$pos + $decalage); + } + return (array($debut,$suite)); + } + else + return (array($texte,'')); +} + +// http://doc.spip.org/@editer_texte_recolle +function editer_texte_recolle($texte, $att_text) +{ + if ((strlen($texte)<29*1024) + OR (include_spip('inc/layer') AND ($GLOBALS['browser_name']!="MSIE")) ) + return array($texte,""); + + include_spip('inc/barre'); + $textes_supplement = "
"._T('info_texte_long')."\n"; + $nombre = 0; + + while (strlen($texte)>29*1024) { + $nombre ++; + list($texte1,$texte) = coupe_trop_long($texte); + $textes_supplement .= "
" . + "\n"; + } + return array($texte,$textes_supplement); +} + +// Produit la liste des md5 d'un tableau de donnees, sous forme +// de inputs html +// http://doc.spip.org/@controles_md5 +function controles_md5($data, $prefixe='ctr_', $format='html'){ + if (!is_array($data)) + return false; + + $ctr = array(); + foreach ($data as $key => $val) { + $m = md5($val); + $k = $prefixe.$key; + + switch ($format) { + case 'html': + $ctr[$k] = ""; + break; + default: + $ctr[$k] = $m; + break; + } + } + + if ($format == 'html') + return "\n\n\n".join("\n", $ctr)."\n\n"; + else + return $ctr; +} + +// http://doc.spip.org/@controler_contenu +function controler_contenu($type, $id, $options=array(), $c=false, $serveur='') { + include_spip('inc/filtres'); + + $table_objet = table_objet($type); + $spip_table_objet = table_objet_sql($type); + $id_table_objet = id_table_objet($type); + $trouver_table = charger_fonction('trouver_table', 'base'); + $desc = $trouver_table($table_objet, $serveur); + + // Appels incomplets (sans $c) + if (!is_array($c)) { + foreach($desc['field'] as $champ=>$ignore) + if(_request($champ)) + $c[$champ] = _request($champ); + } + + // Securite : certaines variables ne sont jamais acceptees ici + // car elles ne relevent pas de autoriser(article, modifier) ; + // il faut passer par instituer_XX() + // TODO: faut-il passer ces variables interdites + // dans un fichier de description separe ? + unset($c['statut']); + unset($c['id_parent']); + unset($c['id_rubrique']); + unset($c['id_secteur']); + + // Gerer les champs non vides + if (is_array($options['nonvide'])) + foreach ($options['nonvide'] as $champ => $sinon) + if ($c[$champ] === '') + $c[$champ] = $sinon; + + // N'accepter que les champs qui existent + // TODO: ici aussi on peut valider les contenus + // en fonction du type + $champs = array(); + foreach($desc['field'] as $champ => $ignore) + if (isset($c[$champ])) + $champs[$champ] = $c[$champ]; + + // Nettoyer les valeurs + $champs = array_map('corriger_caracteres', $champs); + + // Envoyer aux plugins + $champs = pipeline('pre_edition', + array( + 'args' => array( + 'table' => $spip_table_objet, // compatibilite + 'table_objet' => $table_objet, + 'spip_table_objet' => $spip_table_objet, + 'type' =>$type, + 'id_objet' => $id, + 'champs' => $options['champs'], + 'action' => 'controler' + ), + 'data' => $champs + ) + ); + + if (!$champs) return array(); + + // Verifier si les mises a jour sont pertinentes, datees, en conflit etc + $conflits = controler_md5($champs, $_POST, $type, $id, $serveur, $options['prefix']?$options['prefix']:'ctr_'); + + return $conflits; +} + +// Controle la liste des md5 envoyes, supprime les inchanges, +// signale les modifies depuis telle date +// http://doc.spip.org/@controler_md5 +function controler_md5(&$champs, $ctr, $type, $id, $serveur, $prefix = 'ctr_') { + $table_objet = table_objet($type); + $spip_table_objet = table_objet_sql($type); + $id_table_objet = id_table_objet($type); + + // Controle des MD5 envoyes + // On elimine les donnees non modifiees par le formulaire (mais + // potentiellement modifiees entre temps par un autre utilisateur) + foreach ($champs as $key => $val) { + if ($m = $ctr[$prefix.$key]) { + if ($m == md5($val)) + unset ($champs[$key]); + } + } + if (!$champs) return array(); + + // On veut savoir si notre modif va avoir un impact + // par rapport aux donnees contenues dans la base + // (qui peuvent etre differentes de celles ayant servi a calculer le ctr) + $s = sql_fetsel(array_keys($champs), $spip_table_objet, "$id_table_objet=$id", $serveur); + $intact = true; + foreach ($champs as $ch => $val) + $intact &= ($s[$ch] == $val); + if ($intact) return array(); + + // Detection de conflits : + // On verifie si notre modif ne provient pas d'un formulaire + // genere a partir de donnees modifiees dans l'intervalle ; ici + // on compare a ce qui est dans la base, et on bloque en cas + // de conflit. + $ctrh = $ctrq = $conflits = array(); + foreach (array_keys($champs) as $key) { + if ($m = $ctr[$prefix.$key]) { + $ctrh[$key] = $m; + $ctrq[] = $key; + } + } + if ($ctrq) { + $ctrq = sql_fetsel($ctrq, $spip_table_objet, "$id_table_objet=$id", $serveur); + foreach ($ctrh as $key => $m) { + if ($m != md5($ctrq[$key]) + AND $champs[$key] !== $ctrq[$key]) { + $conflits[$key] = array( + 'base' => $ctrq[$key], + 'post' => $champs[$key] + ); + unset($champs[$key]); # stocker quand meme les modifs ? + } + } + } + + return $conflits; +} + +// http://doc.spip.org/@display_conflit_champ +function display_conflit_champ($x) { + if (strstr($x, "\n") OR strlen($x)>80) + return "\n"; + else + return "\n"; +} + +// http://doc.spip.org/@signaler_conflits_edition +function signaler_conflits_edition($conflits, $redirect='') { + include_spip('inc/minipres'); + include_spip('inc/revisions'); + include_spip('inc/suivi_versions'); + include_spip('inc/diff'); + foreach ($conflits as $champ=>$a) { + // probleme de stockage ou conflit d'edition ? + $base = isset($a['save']) ? $a['save'] : $a['base']; + + $diff = new Diff(new DiffTexte); + $n = preparer_diff($a['post']); + $o = preparer_diff($base); + $d = propre_diff( + afficher_para_modifies(afficher_diff($diff->comparer($n,$o)))); + + $titre = isset($a['save']) ? _L('Echec lors de l\'enregistrement du champ @champ@', array('champ' => $champ)) : $champ; + + $diffs[] = "

$titre

\n" + . "

"._T('info_conflit_edition_differences')."

\n" + . "
".$d."
\n" + . "

"._T('info_conflit_edition_votre_version')."

" + . display_conflit_champ($a['post']) + . "

"._T('info_conflit_edition_version_enregistree')."

" + . display_conflit_champ($base); + } + + if ($redirect) { + $id = uniqid(rand()); + $redirect = "
\n" + .form_hidden($redirect) + ." +
\n"; + + // pour les documents, on est probablement en ajax : il faut ajaxer + if (_AJAX) + $redirect .= '\n"; + + } + + echo minipres( + _T('titre_conflit_edition'), + + '' + .'

'._T('info_conflit_edition_avis_non_sauvegarde').'

' + .'

'._T('texte_conflit_edition_correction').'

' + ."
" + . join("\n",$diffs) + ."
\n" + + . $redirect + ); +} + +?>