From: Ludovic CHEVALIER Date: Tue, 6 Sep 2016 14:23:54 +0000 (+0200) Subject: [PLUGINS] ~maj Crayons X-Git-Tag: v3.3.0~91 X-Git-Url: http://git.cyclocoop.org/?p=lhc%2Fweb%2Fwww.git;a=commitdiff_plain;h=50522c53acc9e61a4a7de3a1890c4ba93e2f61b4 [PLUGINS] ~maj Crayons --- diff --git a/www/plugins/crayons/action/crayons.php b/www/plugins/crayons/action/crayons.php index bd7a7c82..8bdc3651 100644 --- a/www/plugins/crayons/action/crayons.php +++ b/www/plugins/crayons/action/crayons.php @@ -1,12 +1,14 @@ \ No newline at end of file diff --git a/www/plugins/crayons/action/crayons_html.php b/www/plugins/crayons/action/crayons_html.php index b9c63857..1af505bd 100644 --- a/www/plugins/crayons/action/crayons_html.php +++ b/www/plugins/crayons/action/crayons_html.php @@ -1,12 +1,14 @@ ''); if (preg_match(_PREG_CRAYON, $class, $regs)) { @@ -29,27 +31,29 @@ function affiche_controleur($class, $c=null) { $regs[] = $class; // A-t-on le droit de crayonner ? - spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$champ)","crayons_distant"); - if (!autoriser('crayonner',$type, $id, NULL, array('modele'=>$champ))) { + spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$champ)", 'crayons_distant'); + if (!autoriser('crayonner', $type, $id, null, array('modele'=>$champ))) { $return['$erreur'] = "$type $id: " . _U('crayons:non_autorise'); } else { $f = charger_fonction($type.'_'.$champ, 'controleurs', true) - OR $f = charger_fonction($champ, 'controleurs', true) - OR $f = charger_fonction($type, 'controleurs', true) - OR $f = 'controleur_dist'; + or $f = charger_fonction($champ, 'controleurs', true) + or $f = charger_fonction($type, 'controleurs', true) + or $f = 'controleur_dist'; list($html,$status) = $f($regs, $c); - if ($status) + if ($status) { $return['$erreur'] = $html; - else + } else { $return['$html'] = $html; + } } - } else + } else { $return['$erreur'] = _U('crayons:donnees_mal_formatees'); + } return $return; } -function controleur_dist($regs, $c=null) { +function controleur_dist($regs, $c = null) { list( , $nomcrayon, $type, $champ, $id, $class) = $regs; $options = array( 'class' => $class @@ -61,25 +65,26 @@ function controleur_dist($regs, $c=null) { // Attention, un controleur multi-tables ne fonctionnera // que si les champs ont le meme nom dans toutes les tables // (par exemple: hyperlien est ok, mais pas nom) - if (($fichier = find_in_path( - ($controleur = 'controleurs/' . $type . '_' . $champ) . '.html')) - || ($fichier = find_in_path( - ($controleur = 'controleurs/' . $champ) .'.html'))) { - if (!lire_fichier($fichier, $controldata)) + if (($fichier = find_in_path(($controleur = 'controleurs/' . $type . '_' . $champ) . '.html')) + || ($fichier = find_in_path(($controleur = 'controleurs/' . $champ) .'.html'))) { + if (!lire_fichier($fichier, $controldata)) { die('erreur lecture controleur'); - if (preg_match_all('/\bname=(["\'])#ENV\{name_(\w+)\}\1/', - $controldata, $matches, PREG_PATTERN_ORDER)) + } + if (preg_match_all('/\bname=(["\'])#ENV\{name_(\w+)\}\1/', $controldata, $matches, PREG_PATTERN_ORDER)) { $champ = $matches[2]; - } else + } + } else { $controleur = ''; + } $valeur = valeur_colonne_table($type, $champ, $id); #spip_log("$valeur = valeur_colonne_table($type, $champ, $id);"); #spip_log($champ); - if ($valeur === false) + if ($valeur === false) { return array("$type $id $champ: " . _U('crayons:pas_de_valeur'), 6); + } /* if (is_scalar($valeur)) { $valeur = array($champ => $valeur); }*/ @@ -90,19 +95,17 @@ function controleur_dist($regs, $c=null) { $options['hauteurMini'] = 80; // base de hauteur mini $option['inmode'] = 'controleur'; $options['controleur'] = $controleur; - } else - // si la valeur fait plusieurs lignes on doit mettre un textarea - // derogation specifique pour descriptif_site de spip_metas - if ( - preg_match(",[\n\r],", $valeur[$champ]) - OR (($champ == 'valeur') && ($id == 'descriptif_site')) - OR + } elseif (preg_match(",[\n\r],", $valeur[$champ]) + or (($champ == 'valeur') && ($id == 'descriptif_site')) + or // on regarde le type tel que defini dans serial // (attention il y avait des blob dans les vieux spip) ($sqltype = colonne_table($type, $champ)) && - (in_array($sqltype['type'] , array('mediumtext', 'longblob', 'longtext')) || - (($sqltype['type'] == 'text' || $sqltype['type'] == 'blob') - && in_array($champ, array('descriptif', 'bio'))))) { + (in_array($sqltype['type'], array('mediumtext', 'longblob', 'longtext')) || + (($sqltype['type'] == 'text' || $sqltype['type'] == 'blob') + and in_array($champ, array('descriptif', 'bio'))))) { + // si la valeur fait plusieurs lignes on doit mettre un textarea + // derogation specifique pour descriptif_site de spip_metas $options['hauteurMini'] = 80; // hauteur mini d'un textarea $option['inmode'] = 'texte'; } else { // ligne, hauteur naturelle @@ -114,19 +117,18 @@ function controleur_dist($regs, $c=null) { if (is_array($sqltype['long'])) { if (count($sqltype['long']) == 2) { $inputAttrs['maxlength'] = $sqltype['long'][0] + 1 + $sqltype['long'][1]; - } - // on ne sait pas ce que c'est ! - else { + } else { + // on ne sait pas ce que c'est ! $inputAttrs['maxlength'] = $sqltype['long'][0]; } } else { $inputAttrs['maxlength'] = $sqltype['long']; - } + } } } $crayon = new Crayon($nomcrayon, $valeur, $options, $c); - $inputAttrs['style'] = implode('',$crayon->styles); + $inputAttrs['style'] = implode('', $crayon->styles); if (!$controleur) { $inputAttrs['style'] .= 'width:' . $crayon->largeur . 'px;' . @@ -135,7 +137,7 @@ function controleur_dist($regs, $c=null) { $html = $controleur ? $crayon->formulaire(null, $inputAttrs) : $crayon->formulaire($option['inmode'], $inputAttrs); - $status = NULL; + $status = null; return array($html,$status); } @@ -176,7 +178,7 @@ class Crayon { // $name : son nom // $texts : tableau associatif des valeurs ou valeur unique si crayon monochamp // $options : options directes du crayon (developpement) - function Crayon($name, $texts = array(), $options = array(), $c=null) { + function __construct($name, $texts = array(), $options = array(), $c = null) { $this->name = $name; list($this->type, $this->modele, $this->id) = array_pad(explode('-', $this->name, 3), 3, ''); @@ -187,7 +189,7 @@ class Crayon { $this->texts = $texts; $this->key = strtr(uniqid('wid', true), '.', '_'); $this->md5 = $this->md5(); - foreach ($options as $opt=>$val) { + foreach ($options as $opt => $val) { $this->$opt = $val; } $this->dimension($c); @@ -203,8 +205,7 @@ class Crayon { // dimensions indicatives function dimension($c) { // largeur du crayon - $this->largeur = min(max(intval(_request('w', $c)), - $this->largeurMini), $this->largeurMaxi); + $this->largeur = min(max(intval(_request('w', $c)), $this->largeurMini), $this->largeurMaxi); // hauteur maxi d'un textarea selon wh: window height $maxheight = min(max(intval(_request('wh', $c)) - 50, 400), $this->hauteurMaxi); $this->hauteur = min(max(intval(_request('h', $c)), $this->hauteurMini), $maxheight); @@ -218,14 +219,15 @@ class Crayon { // recuperer les elements de style function css() { - foreach(array('color', 'font-size', 'font-family', 'font-weight', 'line-height', 'min-height', 'text-align') as $property) { - if (null !== ($p = _request($property))) + foreach (array('color', 'font-size', 'font-family', 'font-weight', 'line-height', 'min-height', 'text-align') as $property) { + if (null !== ($p = _request($property))) { $this->styles[] = "$property:$p;"; + } } $property = 'background-color'; if (!$p = _request($property) - OR $p == 'transparent') { + or $p == 'transparent') { $p = 'white'; } $this->styles[] = "$property:$p;"; @@ -250,14 +252,14 @@ class Crayon { . ''."\n" . '' + .'" value="'.join(',', array_keys($this->texts)).'" />' ."\n" ; } /** * Fabriquer les balises des champs d'apres un modele controleurs/(type_)modele.html - * + * * @param array $contexte * tableau (nom=>valeur) qui sera enrichi puis passe à recuperer_fond * @return string @@ -277,7 +279,7 @@ class Crayon { foreach ($this->texts as $champ => $val) { $contexte['name_' . $champ] = 'content_' . $this->key . '_' . $champ; } - $contexte['style'] = join(' ',$this->styles); + $contexte['style'] = join(' ', $this->styles); include_spip('public/assembler'); return recuperer_fond($this->controleur, $contexte); } @@ -285,7 +287,7 @@ class Crayon { /** * Fabriquer les balises du ou des champs * $attrs est un tableau (attr=>val) d'attributs communs ou pour le champs unique - * + * * @param string|array $spec * soit un scalaire 'ligne' ou 'texte' précisant le type de balise * soit un array($champ=>array('type'=>'...', 'attrs'=>array(attributs specifique du champs))) @@ -319,12 +321,12 @@ class Crayon { } if (is_array($spec) && isset($spec[$champ]['attrs'])) { - foreach ($spec[$champ]['attrs'] as $attr=>$val) { + foreach ($spec[$champ]['attrs'] as $attr => $val) { $input = inserer_attribut($input, $attr, $val); } } - foreach ($attrs as $attr=>$val) { + foreach ($attrs as $attr => $val) { $input = inserer_attribut($input, $attr, $val); } @@ -332,14 +334,13 @@ class Crayon { // pour faire propre il faudra reprogrammer la bt en jquery $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']) : array(); if (isset($meta_crayon['barretypo']) - AND $meta_crayon['barretypo'] - AND $type == 'texte') { + and $meta_crayon['barretypo'] + and $type == 'texte') { // Pas la peine de mettre cette barre si PortePlume est la - if ( - !( + if (!( function_exists('chercher_filtre') - AND $f = chercher_filtre('info_plugin') - AND $f('PORTE_PLUME','est_actif') + and $f = chercher_filtre('info_plugin') + and $f('PORTE_PLUME', 'est_actif') ) ) { include_spip('inc/barre'); @@ -360,7 +361,7 @@ class Crayon { /** * Fabriquer les boutons du formulaire - * + * * @param array $boutons * Le tableau des boutons * @return string @@ -371,30 +372,34 @@ function crayons_boutons($boutons = array()) { $boutons['cancel'] = array('cancel', texte_backend(_T('crayons:annuler'))); $html = ''; - foreach ($boutons as $bnam => $bdef) if ($bdef) { - $html .= ''; + foreach ($boutons as $bnam => $bdef) { + if ($bdef) { + $html .= ''; + } } - if ($html) + if ($html) { return '
'.$html.'
'; + } } -function crayons_formulaire($html, $action='crayons_store') { - if (!$html) +function crayons_formulaire($html, $action = 'crayons_store') { + if (!$html) { return ''; + } // on est oblige de recreer un Crayon pour connaitre la largeur du form. // Pb conceptuel a revoir - $crayon = new Crayon(""); - $class = ($crayon->largeur<250?" small":""); + $crayon = new Crayon(''); + $class = ($crayon->largeur < 250 ? ' small' : ''); include_spip('inc/filtres'); return liens_absolus( '
' . '
' . $html . crayons_boutons() @@ -408,8 +413,8 @@ function crayons_formulaire($html, $action='crayons_store') { // class SecureCrayon extends Crayon { - function SecureCrayon($name, $text='') { - parent::Crayon($name, $text); + function __construct($name, $text='') { + parent::__construct($name, $text); } function code() { @@ -424,29 +429,29 @@ class SecureCrayon extends Crayon { /** * Action affichant le controleur html ou php adéquat - * + * * on affiche le formulaire demande (controleur associe au crayon) * Si le crayon n'est pas de type "crayon", c'est un crayon etendu, qui * integre le formulaire requis à son controleur (pour avoir les boutons * du formulaire dans un controleur Draggable, par exemple, mais il y a * d'autres usages possibles) - * + * */ function action_crayons_html_dist() { include_spip('inc/crayons'); // Utiliser la bonne langue d'environnement - if(!isset($GLOBALS['forcer_lang']) OR !$GLOBALS['forcer_lang'] OR ($GLOBALS['forcer_lang'] === 'non')) + if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) { lang_select($GLOBALS['auteur_session']['lang']); + } $return = affiche_controleur(_request('class')); - if (!_request('type') OR _request('type') == 'crayon') + if (!_request('type') or _request('type') == 'crayon') { $return['$html'] = crayons_formulaire($return['$html']); + } $json = trim(crayons_json_encode($return)); - header("Content-Type: text/plain; charset=utf-8"); + header('Content-Type: text/plain; charset=utf-8'); die($json); } - -?> diff --git a/www/plugins/crayons/action/crayons_store.php b/www/plugins/crayons/action/crayons_store.php index 85ac1618..b440f7b4 100644 --- a/www/plugins/crayons/action/crayons_store.php +++ b/www/plugins/crayons/action/crayons_store.php @@ -1,17 +1,19 @@ 0) - $content[$field] = $_FILES['content_'.$crayon.'_'.$field]; - else - $content[$field] = false; - // cf. valeur passee dans crayon->md5() : false ou filemtime() du logo - } else { - /** - * le changement de charset n'est plus necessaire - * depuis jquery 1.5 (feature non documentee de jquery!) - */ - if (isset($_POST['content_'.$crayon.'_'.$field])) { - $content[$field] = is_array($_POST['content_'.$crayon.'_'.$field]) - ?implode(',',$_POST['content_'.$crayon.'_'.$field]) - :$_POST['content_'.$crayon.'_'.$field]; + if (isset($_POST['crayons']) and is_array($_POST['crayons'])) { + foreach ($_POST['crayons'] as $crayon) { + $name = $_POST['name_'.$crayon]; + $content = array(); + if ($_POST['fields_'.$crayon]) { + foreach (explode(',', $_POST['fields_'.$crayon]) as $field) { + // cas particulier d'un envoi de fichier + if (isset($_FILES['content_'.$crayon.'_'.$field])) { + if ($_FILES['content_'.$crayon.'_'.$field]['size'] > 0) { + $content[$field] = $_FILES['content_'.$crayon.'_'.$field]; + } else { + $content[$field] = false; + } + // cf. valeur passee dans crayon->md5() : false ou filemtime() du logo } else { - $content[$field] = null; + /** + * le changement de charset n'est plus necessaire + * depuis jquery 1.5 (feature non documentee de jquery!) + */ + if (isset($_POST['content_'.$crayon.'_'.$field])) { + $content[$field] = is_array($_POST['content_'.$crayon.'_'.$field]) + ?implode(',', $_POST['content_'.$crayon.'_'.$field]) + :$_POST['content_'.$crayon.'_'.$field]; + } else { + $content[$field] = null; + } } } } - } - // Si les donnees POSTees ne correspondent pas a leur md5, - // il faut les traiter - if (isset($name) - AND md5(serialize($content)) != $_POST['md5_'.$crayon]) { - if (!isset($_POST['secu_'.$crayon]) - OR verif_secu($name, $_POST['secu_'.$crayon])) { - $results[] = array($name, $content, $_POST['md5_'.$crayon], $crayon); + // Si les donnees POSTees ne correspondent pas a leur md5, + // il faut les traiter + if (isset($name) + and md5(serialize($content)) != $_POST['md5_'.$crayon]) { + if (!isset($_POST['secu_'.$crayon]) + or verif_secu($name, $_POST['secu_' . $crayon])) { + $results[] = array($name, $content, $_POST['md5_'.$crayon], $crayon); + } else { + return false; // erreur secu + } + } else { + // cas inchange + $results[] = array($name, $content, false, $crayon); } - else - return false; // erreur secu } - // cas inchange - else - $results[] = array($name, $content, false, $crayon); } - return $results; } @@ -87,70 +90,70 @@ function crayons_store($options = array()) { if (!is_array($postees)) { $return['$erreur'] = _U('crayons:donnees_mal_formatees'); } else { - foreach ($postees as $postee) - if ($postee[2] !== false) { - $name = $postee[0]; - $content = $postee[1]; - - if ($content && preg_match(_PREG_CRAYON, 'crayon '.$name, $regs)) { - list(,$crayon,$type,$modele,$id) = $regs; - $wid = $postee[3]; - - spip_log("autoriser('crayonner', $type, $id, NULL, array('modele'=>$modele)","crayons_distant"); - if (!autoriser('crayonner', $type, $id, NULL, array('modele'=>$modele))) { - $return['$erreur'] = - "$type $id: " . _U('crayons:non_autorise'); - } else { + foreach ($postees as $postee) { + if ($postee[2] !== false) { + $name = $postee[0]; + $content = $postee[1]; + + if ($content && preg_match(_PREG_CRAYON, 'crayon '.$name, $regs)) { + list(,$crayon,$type,$modele,$id) = $regs; + $wid = $postee[3]; + + spip_log("autoriser('crayonner', $type, $id, null, array('modele' => $modele)", 'crayons_distant'); + if (!autoriser('crayonner', $type, $id, null, array('modele' => $modele))) { + $return['$erreur'] = + "$type $id: " . _U('crayons:non_autorise'); + } else { + // recuperer l'existant pour calculer son md5 et verifier + // qu'il n'a pas ete modifie entre-temps + $get_valeur = $options['f_get_valeur']; + $data = $get_valeur($content, $regs); + + $md5 = md5(serialize($data)); + + // est-ce que le champ a ete modifie dans la base entre-temps ? + if ($md5 != $postee[2]) { + // si oui, la modif demandee correspond peut-etre + // a la nouvelle valeur ? dans ce cas on procede + // comme si "pas de modification", sinon erreur + if ($md5 != md5(serialize($content))) { + $return['$erreur'] = "$type $id $modele: " . + _U('crayons:modifie_par_ailleurs'); + } + } - // recuperer l'existant pour calculer son md5 et verifier - // qu'il n'a pas ete modifie entre-temps - $get_valeur = $options['f_get_valeur']; - $data = $get_valeur($content, $regs); - - $md5 = md5(serialize($data)); - - // est-ce que le champ a ete modifie dans la base entre-temps ? - if ($md5 != $postee[2]) { - // si oui, la modif demandee correspond peut-etre - // a la nouvelle valeur ? dans ce cas on procede - // comme si "pas de modification", sinon erreur - if ($md5 != md5(serialize($content))) { - $return['$erreur'] = "$type $id $modele: " . - _U('crayons:modifie_par_ailleurs'); + $modifs[] = array($type, $modele, $id, $content, $wid); + + /* aiguillage pour verification de la saisie + Pour traitement ulterieur les fonctions de verifications doivent renvoyer $invalides : + $invalides[wid_champ]['msg'] -> message de saisie invalide + $invalides[wid_champ]['retour'] -> caracteres invalides */ + $f = 'verifier_'.$type.'_'.$modele; + if (function_exists($f)) { + if (count($invalides = $f($modifs))) { + $return['$invalides'] = $invalides; + } } } - - $modifs[] = array($type, $modele, $id, $content, $wid); - - /* aiguillage pour verification de la saisie - Pour traitement ulterieur les fonctions de verifications doivent renvoyer $invalides : - $invalides[wid_champ]['msg'] -> message de saisie invalide - $invalides[wid_champ]['retour'] -> caracteres invalides */ - $f = 'verifier_'.$type.'_'.$modele; - if (function_exists($f)) { - if (count( $invalides = $f($modifs) )) { - $return['$invalides'] = $invalides; - } - - } } } } } - if (!$modifs AND !$return['$erreur']) { - $return['$erreur'] = $wdgcfg['msgNoChange'] ? - _U('crayons:pas_de_modification') : ' '; + if (!$modifs and !$return['$erreur']) { + $return['$erreur'] = $wdgcfg['msgNoChange'] ? _U('crayons:pas_de_modification') : ' '; $return['$annuler'] = true; } - - // un champ invalide ... ou rien ==> on ne fait rien ! - if (isset($return['$invalides']) && $return['$invalides']) + + // un champ invalide ... ou rien ==> on ne fait rien ! + if (isset($return['$invalides']) and $return['$invalides']) { return $return; + } // une quelconque erreur ... ou rien ==> on ne fait rien ! - if (isset($return['$erreur']) && $return['$erreur']) + if (isset($return['$erreur']) and $return['$erreur']) { return $return; + } // on traite toutes les modifications // en appelant la fonction adequate de traitement @@ -158,17 +161,18 @@ function crayons_store($options = array()) { $return = $set_modifs($modifs, $return); // une quelconque erreur ... ou rien ==> on ne fait rien ! - if ($return['$erreur']) + if ($return['$erreur']) { return $return; + } // et maintenant refaire l'affichage des crayons modifies include_spip('inc/texte'); foreach ($modifs as $m) { list($type, $modele, $id, $content, $wid) = $m; $f = charger_fonction($type.'_'.$modele, 'vues', true) - OR $f = charger_fonction($modele, 'vues', true) - OR $f = charger_fonction($type, 'vues', true) - OR $f = 'vues_dist'; + or $f = charger_fonction($modele, 'vues', true) + or $f = charger_fonction($type, 'vues', true) + or $f = 'vues_dist'; $return[$wid] = $f($type, $modele, $id, $content, $wid); } return $return; @@ -192,64 +196,62 @@ function crayons_store_set_modifs($modifs, $return) { $fun = ''; // si le crayon est un MODELE avec une fonction xxx_revision associee // cas ou une fonction xxx_revision existe - if (function_exists($f = $type.'_'. $modele . "_revision") - OR function_exists($f = $modele . "_revision") - OR function_exists($f = $type . "_revision")) + if (function_exists($f = $type.'_'. $modele . '_revision') + or function_exists($f = $modele . '_revision') + or function_exists($f = $type . '_revision')) { $fun = $f; - - // si on est en SPIP 3+ et qu'on edite un objet editorial bien declare - // passer par l'API objet_modifier - elseif (function_exists('lister_tables_objets_sql') - AND $tables_objet = lister_tables_objets_sql() - AND isset($tables_objet[table_objet_sql($type)])) { + } elseif (function_exists('lister_tables_objets_sql') + and $tables_objet = lister_tables_objets_sql() + and isset($tables_objet[table_objet_sql($type)])) { + // si on est en SPIP 3+ et qu'on edite un objet editorial bien declare + // passer par l'API objet_modifier $fun = 'crayons_objet_modifier'; - } - - // sinon spip < 3 (ou pas un objet edito) - // on teste les objets connus et on route sur les fonctions correspondantes - else switch($type) { - case 'article': - $fun = 'crayons_update_article'; - break; - case 'breve': - include_spip('action/editer_breve'); - $fun = 'revisions_breves'; - break; - case 'forum': - include_spip('inc/forum'); - $fun = 'enregistre_et_modifie_forum'; - break; - case 'rubrique': - include_spip('action/editer_rubrique'); - $fun = 'revisions_rubriques'; - break; - case 'syndic': - case 'site': - include_spip('action/editer_site'); - $fun = 'revisions_sites'; - break; - case 'document': - include_spip('plugins/installer'); - include_spip('inc/plugin'); - if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) { - include_spip('action/editer_document'); - $fun = 'document_modifier'; - } else { + } else { + // sinon spip < 3 (ou pas un objet edito) + // on teste les objets connus et on route sur les fonctions correspondantes + switch ($type) { + case 'article': + $fun = 'crayons_update_article'; + break; + case 'breve': + include_spip('action/editer_breve'); + $fun = 'revisions_breves'; + break; + case 'forum': + include_spip('inc/forum'); + $fun = 'enregistre_et_modifie_forum'; + break; + case 'rubrique': + include_spip('action/editer_rubrique'); + $fun = 'revisions_rubriques'; + break; + case 'syndic': + case 'site': + include_spip('action/editer_site'); + $fun = 'revisions_sites'; + break; + case 'document': + include_spip('plugins/installer'); + include_spip('inc/plugin'); + if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) { + include_spip('action/editer_document'); + $fun = 'document_modifier'; + } else { + include_spip('inc/modifier'); + $fun = 'revision_document'; + } + break; + // cas geres de la maniere la plus standard + case 'auteur': + case 'mot': + case 'signature': + case 'petition': + default: include_spip('inc/modifier'); - $fun = 'revision_document'; - } - break; - // cas geres de la maniere la plus standard - case 'auteur': - case 'mot': - case 'signature': - case 'petition': - default: - include_spip('inc/modifier'); - $fun = 'revision_'.$type; - break; + $fun = 'revision_'.$type; + break; + } } - // si on a pas reussi on passe par crayons_update() qui fera un update sql brutal if (!$fun or !function_exists($fun)) { $fun = 'crayons_update'; @@ -271,11 +273,12 @@ function crayons_store_set_modifs($modifs, $return) { } // il manque une fonction de mise a jour ==> on ne fait rien ! - if ($return['$erreur']) + if ($return['$erreur']) { return $return; + } // hop ! mises a jour table par table et id par id - foreach ($updates as $type => $idschamps) + foreach ($updates as $type => $idschamps) { foreach ($idschamps as $fun => $ids) { foreach ($ids as $id => $champsvaleurs) { /* cas particulier du logo dans un crayon complexe : @@ -289,21 +292,23 @@ function crayons_store_set_modifs($modifs, $return) { // -- revisions_articles($id_article, $c) -- spip_log("$fun($id ...)", 'crayons'); $updok = $fun($id, $champsvaleurs['chval'], $type, $champsvaleurs['wdg']); - // Renvoyer erreur si update base distante echoue, on ne regarde pas les updates base local car ils ne renvoient rien + // Renvoyer erreur si update base distante echoue, + // on ne regarde pas les updates base local car ils ne renvoient rien list($distant,$table) = distant_table($type); - if ($distant AND !$updok) + if ($distant and !$updok) { $return['$erreur'] = "$type: " . _U('crayons:update_impossible'); + } } } } - + } return $return; } // // VUE // -function vues_dist($type, $modele, $id, $content, $wid){ +function vues_dist($type, $modele, $id, $content, $wid) { // pour ce qui a une {lang_select} par defaut dans la boucle, // la regler histoire d'avoir la bonne typo dans le propre() // NB: ceci n'a d'impact que sur le "par defaut" en bas @@ -317,11 +322,12 @@ function vues_dist($type, $modele, $id, $content, $wid){ // chercher vues/article_toto.html // sinon vues/toto.html - if (find_in_path( ($fond = 'vues/' . $type . '_' . $modele) . '.html') - OR find_in_path( ($fond = 'vues/' . $modele) .'.html') - OR find_in_path( ($fond = 'vues/' . $type) .'.html')) { + if (find_in_path(($fond = 'vues/' . $type . '_' . $modele) . '.html') + or find_in_path(($fond = 'vues/' . $modele) .'.html') + or find_in_path(($fond = 'vues/' . $type) .'.html')) { + $primary = (function_exists('id_table_objet')?id_table_objet($table):'id_' . $table); $contexte = array( - 'id_' . $table => $id, + $primary => $id, 'crayon_type' => $type, 'crayon_modele' => $modele, 'champ' => $modele, @@ -332,9 +338,8 @@ function vues_dist($type, $modele, $id, $content, $wid){ $contexte = array_merge($contexte, $content); include_spip('public/assembler'); return recuperer_fond($fond, $contexte); - } - // vue par defaut - else { + } else { + // vue par defaut // Par precaution on va rechercher la valeur // dans la base de donnees (meme si a priori la valeur est // ce qu'on vient d'envoyer, il y a nettoyage des caracteres et @@ -355,13 +360,19 @@ function vues_dist($type, $modele, $id, $content, $wid){ } } - // seul spip core sait rendre les donnees - if (in_array($modele, - array('chapo', 'texte', 'descriptif', 'ps', 'bio'))) { - return propre($valeur); - } else { - return typo($valeur); + if ($valeur) { + // seul spip core sait rendre les donnees + if (function_exists('appliquer_traitement_champ')) { + $valeur = appliquer_traitement_champ($valeur, $modele, table_objet($table)); + } else { + if (in_array($modele, array('chapo', 'texte', 'descriptif', 'ps', 'bio'))) { + $valeur = propre($valeur); + } else { + $valeur = typo($valeur); + } + } } + return $valeur; } } @@ -376,8 +387,8 @@ function vues_dist($type, $modele, $id, $content, $wid){ */ function crayons_objet_modifier($id, $data, $type, $ref) { if (include_spip('action/editer_objet') - AND function_exists('objet_modifier')) { - return objet_modifier(objet_type($type),$id,$data); + and function_exists('objet_modifier')) { + return objet_modifier(objet_type($type), $id, $data); } // fallback return crayons_update($id, $data, $type); @@ -386,15 +397,17 @@ function crayons_objet_modifier($id, $data, $type, $ref) { // // Fonctions de mise a jour generique // -function crayons_update($id, $colval = array(), $type = ''){ - if (!$colval OR !count($colval)) +function crayons_update($id, $colval = array(), $type = '') { + if (!$colval or !count($colval)) { return false; + } list($distant,$table) = distant_table($type); if ($distant) { list($nom_table, $where) = table_where($type, $id); - if (!$nom_table) + if (!$nom_table) { return false; + } $update = $sep = ''; foreach ($colval as $col => $val) { @@ -402,14 +415,12 @@ function crayons_update($id, $colval = array(), $type = ''){ $sep = ', '; } - $a = spip_query($q = - 'UPDATE `' . $nom_table . '` SET ' . $update . ' WHERE ' . $where , $distant ); + $a = spip_query($q = 'UPDATE `' . $nom_table . '` SET ' . $update . ' WHERE ' . $where, $distant); #spip_log($q); include_spip('inc/invalideur'); - suivre_invalideur($cond, $modif=true); - } - else { + suivre_invalideur($cond, $modif = true); + } else { // cle primaire composee : 3-4-rubrique // calculer un where approprie // et modifier sans passer par la fonction destinee aux tables principales @@ -423,7 +434,6 @@ function crayons_update($id, $colval = array(), $type = ''){ $a = modifier_contenu($type, $id, array(), $colval); } } - return $a; } @@ -440,7 +450,7 @@ function crayons_update_article($id_article, $c = false) { // NB: instituer_article veut id_parent, et pas id_rubrique ! if (isset($c['id_rubrique'])) { $c['id_parent'] = $c['id_rubrique']; - unset ($c['id_rubrique']); + unset($c['id_rubrique']); } instituer_article($id_article, $c); } @@ -452,7 +462,7 @@ function crayons_update_article($id_article, $c = false) { * La colonne est toujours 'valeur' pour ces données. * La donnée à enregistrer peut-être une sous partie de configuration. * Si c'est le cas, on gère l'enregistrement via ecrire_config. - * + * * @param string $a * Nom ou clé de la meta (descriptif_site ou demo__truc pour demo/truc) * @param bool|array $c @@ -493,7 +503,7 @@ function action_crayons_store_dist() { // permettre de passer une autre fonction de stockage des informations function action_crayons_store_args($store = 'crayons_store') { - header("Content-Type: text/plain; charset=".$GLOBALS['meta']['charset']); + header('Content-Type: text/plain; charset='.$GLOBALS['meta']['charset']); lang_select($GLOBALS['auteur_session']['lang']); $r = $store(); @@ -507,28 +517,25 @@ function action_crayons_store_args($store = 'crayons_store') { // En cas d'erreur il faudrait ajouter &err=... dans l'url ? if (_request('redirect')) { if (!$r['$erreur'] - OR $r['$annuler']) { + or $r['$annuler']) { include_spip('inc/headers'); redirige_par_entete(_request('redirect')); } else { echo "

".$r['$erreur']."

\n"; foreach ($r as $wid => $v) { - if ($wid !== '$erreur') + if ($wid !== '$erreur') { echo "
$v

\n"; + } } echo "" .quote_amp(_request('redirect')) ."\n"; } - } - - // Cas normal : JSON - else { + } else { + // Cas normal : JSON echo crayons_json_export($r); } exit; } - -?> diff --git a/www/plugins/crayons/action/crayons_upload.php b/www/plugins/crayons/action/crayons_upload.php index f09e7bef..38b80996 100644 --- a/www/plugins/crayons/action/crayons_upload.php +++ b/www/plugins/crayons/action/crayons_upload.php @@ -1,16 +1,18 @@ =')) + $nom_envoye = $file['name']; # mon-image.jpg + + include_spip('plugins/installer'); // spip_version_compare dans SPIP 3.x + include_spip('inc/plugin'); // spip_version_compare dans SPIP 2.x + if (function_exists('spip_version_compare')) { // gerer son absence dans les branche precedente a SPIP 2.x + if (spip_version_compare($GLOBALS['spip_version_branche'], '3.0.0alpha', '>=')) { define('_SPIP3', true); - } + } + } if (defined('_SPIP3')) { include_spip('action/ajouter_documents'); - $ajouter_un_document = charger_fonction('ajouter_un_document','action'); - $id = $ajouter_un_document("new", $file, $type, $id, 'document'); + $ajouter_un_document = charger_fonction('ajouter_un_document', 'action'); + $id = $ajouter_un_document('new', $file, $type, $id, 'document'); } else { include_spip('inc/ajouter_documents'); - $id = ajouter_un_document($source, $nom_envoye, $type, $id, 'document', $id_document=0, $documents_actifs, $titrer=true); + $id = ajouter_un_document($source, $nom_envoye, $type, $id, 'document', $id_document = 0, $documents_actifs, $titrer = true); } } - if (!$id) - $erreur = "erreur !"; + if (!$id) { + $erreur = 'erreur !'; + } - $a = recuperer_fond('modeles/uploader_item',array('id_document' => $id, 'erreur' => $erreur)); + $a = recuperer_fond('modeles/uploader_item', array('id_document' => $id, 'erreur' => $erreur)); echo $a; } - -?> diff --git a/www/plugins/crayons/controleurs/article_intro3.php b/www/plugins/crayons/controleurs/article_intro3.php index 491cb704..557f676c 100644 --- a/www/plugins/crayons/controleurs/article_intro3.php +++ b/www/plugins/crayons/controleurs/article_intro3.php @@ -1,39 +1,38 @@ 234)); - $n = new Crayon('article-intro3-' . $id, $valeur, - array('hauteurMini' => 234)); - - $return = array( - // html - $n->formulaire( - // champs et attributs propres - array( - 'descriptif' => array('type' => 'texte', 'attrs' => array( - 'style' => 'height:' . ceil($n->hauteur*2/13) . 'px;' . - 'width:' . $n->largeur . 'px;')), + $return = array( + // html + $n->formulaire( + // champs et attributs propres + array( + 'descriptif' => array('type' => 'texte', 'attrs' => array( + 'style' => 'height:' . ceil($n->hauteur*2/13) . 'px;' . + 'width:' . $n->largeur . 'px;')), 'chapo' => array('type' => 'texte', 'attrs' => array( - 'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' . - 'width:' . $n->largeur . 'px;')), + 'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' . + 'width:' . $n->largeur . 'px;')), 'texte' => array('type' => 'texte', 'attrs' => array( - 'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' . - 'width:' . $n->largeur . 'px;'))) //, - // attributs communs :( marche pas pour style , pas 2 fois ? -// array('style' => 'width:' . $n->largeur . 'px;') - ), - // status - null); + 'style' => 'height:' . ceil($n->hauteur*4/13) . 'px;' . + 'width:' . $n->largeur . 'px;'))) //, + // attributs communs :( marche pas pour style , pas 2 fois ? + // array('style' => 'width:' . $n->largeur . 'px;') + ), + // status + null); return $return; } - -?> diff --git a/www/plugins/crayons/controleurs/article_introduction.html b/www/plugins/crayons/controleurs/article_introduction.html index 75bb5bf9..53d16945 100644 --- a/www/plugins/crayons/controleurs/article_introduction.html +++ b/www/plugins/crayons/controleurs/article_introduction.html @@ -18,11 +18,11 @@ ] #CACHE{0} -
    +
    • <:crayons:legend_introduction_article:>

      <:crayons:explication_introduction_article:>

      -
        +
        • +
        • +
        • + + +
        • +
        + + diff --git a/www/plugins/crayons/controleurs/rubrique_introduction.php b/www/plugins/crayons/controleurs/rubrique_introduction.php new file mode 100644 index 00000000..c1000afa --- /dev/null +++ b/www/plugins/crayons/controleurs/rubrique_introduction.php @@ -0,0 +1,29 @@ + 234, 'controleur' => 'controleurs/rubrique_introduction') + ); + + $contexte = array( + 'h_descriptif' => (int)ceil($n->hauteur*5/13), + 'h_texte' => (int)ceil($n->hauteur*7/13)); + $html = $n->formulaire($contexte); + $status = null; + + return array($html, $status); +} diff --git a/www/plugins/crayons/controleurs/vignette.html b/www/plugins/crayons/controleurs/vignette.html index db99f927..15bd12eb 100644 --- a/www/plugins/crayons/controleurs/vignette.html +++ b/www/plugins/crayons/controleurs/vignette.html @@ -28,22 +28,20 @@ })] })] -
          -
        • -

          - [(#GET{legend}|sinon{<:crayons:legend_controleur_vignette:>})] - [
          (#GET{vignette}|inserer_attribut{src,#GET{url}} - |inserer_attribut{style,vertical-align:middle;})
          ] -

          -
            -
          • -
            - -
            - #GET{supprimer} -
          • -
          -
        • -
        +
        +

        + [(#GET{legend}|sinon{<:crayons:legend_controleur_vignette:>})] + [
        (#GET{vignette}|inserer_attribut{src,#GET{url}} + |inserer_attribut{style,vertical-align:middle;})
        ] +

        +
          +
        • +
          + +
          + #GET{supprimer} +
        • +
        +
        \ No newline at end of file diff --git a/www/plugins/crayons/crayons.js.html b/www/plugins/crayons/crayons.js.html index 748b8e9f..6448ca4b 100644 --- a/www/plugins/crayons/crayons.js.html +++ b/www/plugins/crayons/crayons.js.html @@ -19,17 +19,15 @@ cQuery.noConflict(); [(#CHEMIN{js/jquery.form.js}|pack_cQuery)] -[(#CHEMIN{js/jquery.px.js}|pack_cQuery)] - [(#CHEMIN{js/crayons.js}|pack_cQuery)] [(#CHEMIN{js/resizehandle.js}|pack_cQuery)] -[(#CHEMIN{js/jquery.html5uploader.min.js}|pack_cQuery)] +[(#CHEMIN{js/jquery.html5uploader.js}|pack_cQuery)] [(#CONFIG{crayons}|match{s:11:"yellow_fade";s:2:"on";}|?{' ',''}) [(#CHEMIN{js/crayons-fade.js}|pack_cQuery)] ] [(#REM) Appeler la callback si demandee ] -[(#ENV{callback})();] \ No newline at end of file +[(#ENV{callback})();] diff --git a/www/plugins/crayons/crayons.js_fonctions.php b/www/plugins/crayons/crayons.js_fonctions.php index e427f9eb..17c8e3e5 100644 --- a/www/plugins/crayons/crayons.js_fonctions.php +++ b/www/plugins/crayons/crayons.js_fonctions.php @@ -1,46 +1,48 @@ pack())) + if (strlen($t = $packer->pack())) { return $t; + } // erreur spip_log('erreur de pack_js'); return $flux; } - -?> diff --git a/www/plugins/crayons/crayons_fonctions.php b/www/plugins/crayons/crayons_fonctions.php index b271f557..fd0c89fd 100644 --- a/www/plugins/crayons/crayons_fonctions.php +++ b/www/plugins/crayons/crayons_fonctions.php @@ -1,460 +1,480 @@ -$champ))", "crayons_distant"); - } - if (autoriser('modifier', $type, $id, null, array('champ'=>$champ))) { - if (!isset($droits['.' . $crayon])) { - $droits['.' . $crayon] = 0; - } - $droits['.' . $crayon]++; - $droits_accordes ++; - } - } - - // et les signaler dans la page - if ($droits_accordes == count($regs)) { // tous les droits - $page = Crayons_preparer_page($page, '*', $wdgcfg); - } elseif ($droits) { // seulement certains droits, preciser lesquels - $page = Crayons_preparer_page($page, join(',', array_keys($droits)), $wdgcfg); - } - - return $page; -} - -/** - * Ajoute les scripts css et js nécessaires aux crayons dans le code HTML - * - * @uses crayons_var2js() - * - * @param string $page - * Code HTML de la page complète ou du header seulement - * @param string $droits - * - Liste de css définissant les champs crayonnables - * (séparés par virgule) dont l'édition est autorisée - * - "*" si tous sont autorisés - * @param array $wdgcfg - * Description de la configuration des crayons (attribut => valeur) - * @param string $mode - * - page : toute la page est présente dans `$page` - * - head : seul le header est présent dans `$page` - * @return -**/ -function &Crayons_preparer_page(&$page, $droits, $wdgcfg = array(), $mode = 'page') { - /** - * Si pas forcer_lang, on charge le contrôleur dans la langue que l'utilisateur a dans le privé - */ - if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) { - lang_select($GLOBALS['auteur_session']['lang']); - } - - $jsFile = generer_url_public('crayons.js'); - if (_DEBUG_CRAYONS) { - $jsFile = parametre_url($jsFile, 'debug_crayons', 1, '&'); - } - include_spip('inc/filtres'); // rien que pour direction_css() :( - $cssFile = direction_css(find_in_path('crayons.css')); - - $config = crayons_var2js(array( - 'imgPath' => dirname(find_in_path('images/crayon.png')), - 'droits' => $droits, - 'dir_racine' => _DIR_RACINE, - 'self' => self('&'), - 'txt' => array( - 'error' => _U('crayons:svp_copier_coller'), - 'sauvegarder' => $wdgcfg['msgAbandon'] ? _U('crayons:sauvegarder') : '' - ), - 'img' => array( - 'searching' => array( - 'txt' => _U('crayons:veuillez_patienter') - ), - 'crayon' => array( - 'txt' => _U('crayons:editer') - ), - 'edit' => array( - 'txt' => _U('crayons:editer_tout') - ), - 'img-changed' => array( - 'txt' => _U('crayons:deja_modifie') - ) - ), - 'cfg' => $wdgcfg - )); - - - // Est-ce que PortePlume est la ? - $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']): array(); - $pp = ''; - if (isset($meta_crayon['barretypo']) && $meta_crayon['barretypo']) { - if (function_exists('chercher_filtre') - and $f = chercher_filtre('info_plugin') - and $f('PORTE_PLUME','est_actif')) { - - $pp = <<"; - $incJS = <</* */ - -EOH; - - if ($mode == 'head') { - return $page = $page . $incJS . $incCSS; //js inline avant les css, sinon ca bloque le chargement - } - - $pos_head = strpos($page, ''); - if ($pos_head === false) { - return $page; - } - - // js inline avant la premiere css, ou sinon avant la fin du head - $pos_link = strpos($page, ''); - $page = substr_replace($page, $incCSS, $pos_head, 0); - - return $page; -} - -/** - * Balise indiquant un champ SQL crayonnable - * - * @note - * Si cette fonction est absente, `balise_EDIT_dist()` déclarée par SPIP - * ne retourne rien - * - * @example - * ``` - *
        #TEXTE
        - *
        #PS
        - * ``` - * - * @param Champ $p - * Pile au niveau de la balise - * @return Champ - * Pile complétée par le code à générer -**/ -function balise_EDIT($p) { - - // le code compile de ce qui se trouve entre les {} de la balise - $label = interprete_argument_balise(1, $p); - - // Verification si l'on est dans le cas d'une meta - // #EDIT{meta-descriptif_site} ou #EDIT{meta-demo/truc} - if (preg_match('/meta-(.*)\'/', $label, $meta)) { - $type = 'meta'; - $label= 'valeur'; - $primary = $meta[1]; - $p->code = "classe_boucle_crayon('" - . $type - ."','" - .$label - ."'," - . "str_replace('/', '__', '$primary')" # chaque / doit être remplacé pour CSS. - .").' '"; - $p->interdire_scripts = false; - return $p; - } - - $i_boucle = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle; - // #EDIT hors boucle? ne rien faire - if (!isset($p->boucles[$i_boucle]) or !$type = ($p->boucles[$i_boucle]->type_requete)) { - $p->code = "''"; - $p->interdire_scripts = false; - return $p; - } - - // crayon sur une base distante 'nua__article-intro-5' - if ($distant = $p->boucles[$i_boucle]->sql_serveur) { - $type = $distant.'__'.$type; - } - - // le compilateur 1.9.2 ne calcule pas primary pour les tables secondaires - // il peut aussi arriver une table sans primary (par ex: une vue) - if (!($primary = $p->boucles[$i_boucle]->primary)) { - include_spip('inc/vieilles_defs'); # 1.9.2 pour trouver_def_table - if (function_exists('trouver_def_table')) { - list($nom, $desc) = trouver_def_table( - $p->boucles[$i_boucle]->type_requete, - $p->boucles[$i_boucle] - ); - $primary = $desc['key']['PRIMARY KEY']; - } - } - // On rajoute ici un debug dans le cas où aucune clé primaire n'est trouvée. - // Cela peut se présenter par exemple si on utilise #EDIT{monchamp} directement - // dans une boucle CONDITION sans faire référence au nom de la boucle d'au dessus. - if (!$primary) { - erreur_squelette(_T('crayons:absence_cle_primaire'), $p); - } - - $primary = explode(',', $primary); - $id = array(); - foreach ($primary as $key) { - $id[] = champ_sql(trim($key), $p); - } - $primary = implode(".'-'.", $id); - - $p->code = "classe_boucle_crayon('" - . $type - ."'," - .sinon($label, "''") - ."," - . $primary - .").' '"; - $p->interdire_scripts = false; - return $p; -} - -/** - * Balise indiquant une configuration crayonnable - * - * @example - * ``` - *
        #DESCRIPTIF_SITE_SPIP
        - *
        #CONFIG{demo/truc}
        - * ``` - * - * @param Champ $p - * Pile au niveau de la balise - * @return Champ - * Pile complétée par le code à générer -**/ -function balise_EDIT_CONFIG_dist($p) { - - // le code compile de ce qui se trouve entre les {} de la balise - $config = interprete_argument_balise(1, $p); - if (!$config) { - return $p; - } - - // chaque / du nom de config doit être transformé pour css. - // nous utiliserons '__' à la place. - - $type = 'meta'; - $label= 'valeur'; - - $p->code = "classe_boucle_crayon('" - . $type - . "','" - . $label - . "'," - . "str_replace('/', '__', $config)" - . ").' '"; - $p->interdire_scripts = false; - return $p; -} - -/** - * Crée le controleur du crayon indiqué par la classe CSS - * - * @param string $class - * Class CSS de crayon tel que créé par #EDIT - * @return string - * HTML du crayon, sinon texte d'erreur -**/ -function creer_le_crayon($class) { - include_spip('inc/crayons'); - include_spip('action/crayons_html'); - $a = affiche_controleur($class, array('w' => 485, 'h' => 300, 'wh' => 500)); - return $a['$erreur'] ? $a['$erreur'] : $a['$html']; -} - -/** - * Balise `#CRAYON` affichant un formulaire de crayon - * - * SI `?edit=1;` - * - * @example - * ``` - * #CRAYON{ps} - * ``` - * - * @param Champ $p - * Pile au niveau de la balise - * @return Champ - * Pile complétée par le code à générer -**/ -function balise_CRAYON($p) { - $p = balise_EDIT($p); - $p->code = 'creer_le_crayon('.$p->code.')'; - return $p; -} - - -/** - * Donne la classe CSS crayon - * - * En fonction : - * - du type de la boucle - * (attention aux exceptions pour `#EDIT` dans les boucles HIERARCHIE et SITES) - * - du champ demande (vide, + ou se terminant par + : (+)classe type--id) - * - de l'id courant - * - * @param string $type - * Type d'objet, ou "meta" pour un champ de configuration - * @param string $champ - * Champ SQL concerné - * @param int|string $id - * Identifiant de la ligne sql - * @return string - * Classes CSS (à ajouter dans le HTML à destination du javascript de Crayons) -**/ -function classe_boucle_crayon($type, $champ, $id) { - // $type = objet_type($type); - $type = $type[strlen($type) - 1] == 's' ? - substr($type, 0, -1) : - str_replace( - array('hierarchie','syndication'), - array('rubrique','site'), - $type - ); - - $plus = (substr($champ, -1) == '+' and $champ = substr($champ, 0, -1)) - ? " $type--$id" - : ''; - - // test rapide pour verifier que l'id est valide (a-zA-Z0-9) - if (false !== strpos($id, ' ')) { - spip_log("L'identifiant ($id) ne pourra être géré ($type | $champ)", 'crayons'); - return 'crayon_id_ingerable'; - } - - return 'crayon ' . $type . '-' . $champ . '-' . $id . $plus; -} - -?> + $value) { + $execs[$key] = trim($value); + } + if ($exec_autorise == '*' || in_array($exec, $execs)) { + return true; + } + } + + return false; +} + +/** + * Ajouter la gestion des crayons dans l'espace privé + * + * @pipeline header_prive + * @uses Crayons_preparer_page() + * + * @param string $head + * Contenu du header + * @return string + * Contenu du header +**/ +function Crayons_insert_head($head) { + // verifie la presence d'une meta crayons, si c'est vide + // on ne cherche meme pas a traiter l'espace prive + $config_espace_prive = @unserialize($GLOBALS['meta']['crayons']); + if (empty($config_espace_prive)) { + return $head; + } + + // verifie que l'edition de l'espace prive est autorisee + if (isset($config_espace_prive['espaceprive']) + and $config_espace_prive['espaceprive'] == 'on') { + // determine les pages (exec) crayonnables + if (test_exec_crayonnable(_request('exec'))) { + // Calcul des droits + include_spip('inc/crayons'); + $head = Crayons_preparer_page($head, '*', wdgcfg(), 'head'); + } + } + + // retourne l'entete modifiee + return $head; +} + +/** + * Ajouter la gestion des crayons dans l'espace public + * + * @pipeline affichage_final + * @uses analyse_droits_rapide_dist() + * @uses Crayons_preparer_page() + * @note + * Le pipeline affichage_final est executé à chaque hit sur toute la page + * + * @param string $page + * Contenu de la page à envoyer au navigateur + * @return string + * Contenu de la page à envoyer au navigateur +**/ +function &Crayons_affichage_final(&$page) { + + // ne pas se fatiguer si le visiteur n'a aucun droit + if (!(function_exists('analyse_droits_rapide')?analyse_droits_rapide():analyse_droits_rapide_dist())) { + return $page; + } + + // sinon regarder rapidement si la page a des classes crayon + if (strpos($page, 'crayon')===false) { + return $page; + } + + // voir un peu plus precisement lesquelles + include_spip('inc/crayons'); + if (!preg_match_all(_PREG_CRAYON, $page, $regs, PREG_SET_ORDER)) { + return $page; + } + + $wdgcfg = wdgcfg(); + + // calculer les droits sur ces crayons + include_spip('inc/autoriser'); + $droits = array(); + $droits_accordes = 0; + foreach ($regs as $reg) { + list(,$crayon,$type,$champ,$id) = $reg; + if (_DEBUG_CRAYONS) { + spip_log("autoriser('modifier', $type, $id, NULL, array('champ'=>$champ))", 'crayons_distant'); + } + if (autoriser('modifier', $type, $id, null, array('champ'=>$champ))) { + if (!isset($droits['.' . $crayon])) { + $droits['.' . $crayon] = 0; + } + $droits['.' . $crayon]++; + $droits_accordes ++; + } + } + + // et les signaler dans la page + if ($droits_accordes == count($regs)) { // tous les droits + $page = Crayons_preparer_page($page, '*', $wdgcfg); + } elseif ($droits) { // seulement certains droits, preciser lesquels + $page = Crayons_preparer_page($page, join(',', array_keys($droits)), $wdgcfg); + } + + return $page; +} + +/** + * Ajoute les scripts css et js nécessaires aux crayons dans le code HTML + * + * @uses crayons_var2js() + * + * @param string $page + * Code HTML de la page complète ou du header seulement + * @param string $droits + * - Liste de css définissant les champs crayonnables + * (séparés par virgule) dont l'édition est autorisée + * - "*" si tous sont autorisés + * @param array $wdgcfg + * Description de la configuration des crayons (attribut => valeur) + * @param string $mode + * - page : toute la page est présente dans `$page` + * - head : seul le header est présent dans `$page` + * @return +**/ +function &Crayons_preparer_page(&$page, $droits, $wdgcfg = array(), $mode = 'page') { + /** + * Si pas forcer_lang, on charge le contrôleur dans la langue que l'utilisateur a dans le privé + */ + if (!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang'] or ($GLOBALS['forcer_lang'] === 'non')) { + lang_select($GLOBALS['auteur_session']['lang']); + } + + $jsFile = generer_url_public('crayons.js'); + if (_DEBUG_CRAYONS) { + $jsFile = parametre_url($jsFile, 'debug_crayons', 1, '&'); + } + include_spip('inc/filtres'); // rien que pour direction_css() :( + $cssFile = direction_css(find_in_path('crayons.css')); + + $config = crayons_var2js(array( + 'imgPath' => dirname(find_in_path('images/crayon.png')), + 'droits' => $droits, + 'dir_racine' => _DIR_RACINE, + 'self' => self('&'), + 'txt' => array( + 'error' => _U('crayons:svp_copier_coller'), + 'sauvegarder' => $wdgcfg['msgAbandon'] ? _U('crayons:sauvegarder') : '' + ), + 'img' => array( + 'searching' => array( + 'txt' => _U('crayons:veuillez_patienter') + ), + 'crayon' => array( + 'txt' => _U('crayons:editer') + ), + 'edit' => array( + 'txt' => _U('crayons:editer_tout') + ), + 'img-changed' => array( + 'txt' => _U('crayons:deja_modifie') + ) + ), + 'cfg' => $wdgcfg + )); + + + // Est-ce que PortePlume est la ? + $meta_crayon = isset($GLOBALS['meta']['crayons']) ? unserialize($GLOBALS['meta']['crayons']): array(); + $pp = ''; + if (isset($meta_crayon['barretypo']) && $meta_crayon['barretypo']) { + if (function_exists('chercher_filtre') + and $f = chercher_filtre('info_plugin') + and $f('PORTE_PLUME','est_actif')) { + $pp = <<"; + $incJS = <</* */ + +EOH; + + if ($mode == 'head') { + //js inline avant les css, sinon ca bloque le chargement + $page = $page . $incJS . $incCSS; + return $page; + } + + $pos_head = strpos($page, ''); + if ($pos_head === false) { + return $page; + } + + // js inline avant la premiere css, ou sinon avant la fin du head + $pos_link = strpos($page, ''); + $page = substr_replace($page, $incCSS, $pos_head, 0); + + return $page; +} + +/** + * Balise indiquant un champ SQL crayonnable + * + * @note + * Si cette fonction est absente, `balise_EDIT_dist()` déclarée par SPIP + * ne retourne rien + * + * @example + * ``` + *
        #TEXTE
        + *
        #PS
        + * ``` + * + * @param Champ $p + * Pile au niveau de la balise + * @return Champ + * Pile complétée par le code à générer +**/ +function balise_EDIT($p) { + + // le code compile de ce qui se trouve entre les {} de la balise + $label = interprete_argument_balise(1, $p); + + // Verification si l'on est dans le cas d'une meta + // #EDIT{meta-descriptif_site} ou #EDIT{meta-demo/truc} + if (preg_match('/meta-(.*)\'/', $label, $meta)) { + $type = 'meta'; + $label= 'valeur'; + $primary = $meta[1]; + $p->code = "classe_boucle_crayon('" + . $type + ."','" + .$label + ."'," + . "str_replace('/', '__', '$primary')" # chaque / doit être remplacé pour CSS. + .").' '"; + $p->interdire_scripts = false; + return $p; + } + + $i_boucle = $p->nom_boucle ? $p->nom_boucle : $p->id_boucle; + // #EDIT hors boucle? ne rien faire + if (!isset($p->boucles[$i_boucle]) or !$type = ($p->boucles[$i_boucle]->type_requete)) { + $p->code = "''"; + $p->interdire_scripts = false; + return $p; + } + + // crayon sur une base distante 'nua__article-intro-5' + if ($distant = $p->boucles[$i_boucle]->sql_serveur) { + $type = $distant.'__'.$type; + } + + // le compilateur 1.9.2 ne calcule pas primary pour les tables secondaires + // il peut aussi arriver une table sans primary (par ex: une vue) + if (!($primary = $p->boucles[$i_boucle]->primary)) { + include_spip('inc/vieilles_defs'); # 1.9.2 pour trouver_def_table + if (function_exists('trouver_def_table')) { + list($nom, $desc) = trouver_def_table( + $p->boucles[$i_boucle]->type_requete, + $p->boucles[$i_boucle] + ); + $primary = $desc['key']['PRIMARY KEY']; + } + } + // On rajoute ici un debug dans le cas où aucune clé primaire n'est trouvée. + // Cela peut se présenter par exemple si on utilise #EDIT{monchamp} directement + // dans une boucle CONDITION sans faire référence au nom de la boucle d'au dessus. + if (!$primary) { + erreur_squelette(_T('crayons:absence_cle_primaire'), $p); + } + + $primary = explode(',', $primary); + $id = array(); + foreach ($primary as $key) { + $id[] = champ_sql(trim($key), $p); + } + $primary = implode(".'-'.", $id); + + $p->code = "classe_boucle_crayon('" + . $type + ."'," + .sinon($label, "''") + .',' + . $primary + .").' '"; + $p->interdire_scripts = false; + return $p; +} + +/** + * Balise indiquant une configuration crayonnable + * + * @example + * ``` + *
        #DESCRIPTIF_SITE_SPIP
        + *
        #CONFIG{demo/truc}
        + * ``` + * + * @param Champ $p + * Pile au niveau de la balise + * @return Champ + * Pile complétée par le code à générer +**/ +function balise_EDIT_CONFIG_dist($p) { + + // le code compile de ce qui se trouve entre les {} de la balise + $config = interprete_argument_balise(1, $p); + if (!$config) { + return $p; + } + + // chaque / du nom de config doit être transformé pour css. + // nous utiliserons '__' à la place. + + $type = 'meta'; + $label= 'valeur'; + + $p->code = "classe_boucle_crayon('" + . $type + . "','" + . $label + . "'," + . "str_replace('/', '__', $config)" + . ").' '"; + $p->interdire_scripts = false; + return $p; +} + +/** + * Crée le controleur du crayon indiqué par la classe CSS + * + * @param string $class + * Class CSS de crayon tel que créé par #EDIT + * @return string + * HTML du crayon, sinon texte d'erreur +**/ +function creer_le_crayon($class) { + include_spip('inc/crayons'); + include_spip('action/crayons_html'); + $a = affiche_controleur($class, array('w' => 485, 'h' => 300, 'wh' => 500)); + return $a['$erreur'] ? $a['$erreur'] : $a['$html']; +} + +/** + * Balise `#CRAYON` affichant un formulaire de crayon + * + * SI `?edit=1;` + * + * @example + * ``` + * #CRAYON{ps} + * ``` + * + * @param Champ $p + * Pile au niveau de la balise + * @return Champ + * Pile complétée par le code à générer +**/ +function balise_CRAYON($p) { + $p = balise_EDIT($p); + $p->code = 'creer_le_crayon('.$p->code.')'; + return $p; +} + + +/** + * Donne la classe CSS crayon + * + * En fonction : + * - du type de la boucle + * (attention aux exceptions pour `#EDIT` dans les boucles HIERARCHIE et SITES) + * - du champ demande (vide, + ou se terminant par + : (+)classe type--id) + * - de l'id courant + * + * @param string $type + * Type d'objet, ou "meta" pour un champ de configuration + * @param string $champ + * Champ SQL concerné + * @param int|string $id + * Identifiant de la ligne sql + * @return string + * Classes CSS (à ajouter dans le HTML à destination du javascript de Crayons) +**/ +function classe_boucle_crayon($type, $champ, $id) { + // $type = objet_type($type); + $type = $type[strlen($type) - 1] == 's' ? + substr($type, 0, -1) : + str_replace( + array('hierarchie','syndication'), + array('rubrique','site'), + $type + ); + + $plus = (substr($champ, -1) == '+' and $champ = substr($champ, 0, -1)) + ? " $type--$id" + : ''; + + // test rapide pour verifier que l'id est valide (a-zA-Z0-9) + if (false !== strpos($id, ' ')) { + spip_log("L'identifiant ($id) ne pourra être géré ($type | $champ)", 'crayons'); + return 'crayon_id_ingerable'; + } + + return 'crayon ' . $type . '-' . $champ . '-' . $id . $plus; +} diff --git a/www/plugins/crayons/inc/compat_crayons.php b/www/plugins/crayons/inc/compat_crayons.php index 5eba6939..db6456c7 100644 --- a/www/plugins/crayons/inc/compat_crayons.php +++ b/www/plugins/crayons/inc/compat_crayons.php @@ -1,85 +1,90 @@ - + }'; + + // Contourner un bug du plugin CFG + include_spip('base/abstract_sql'); + + return $defs; +} diff --git a/www/plugins/crayons/inc/crayons-json.php b/www/plugins/crayons/inc/crayons-json.php index 5311c5e7..93a30b34 100644 --- a/www/plugins/crayons/inc/crayons-json.php +++ b/www/plugins/crayons/inc/crayons-json.php @@ -1,18 +1,20 @@ diff --git a/www/plugins/crayons/inc/crayons.php b/www/plugins/crayons/inc/crayons.php index ed40b6e9..7bcf64d3 100644 --- a/www/plugins/crayons/inc/crayons.php +++ b/www/plugins/crayons/inc/crayons.php @@ -1,682 +1,720 @@ -\'"]+?\b((\w+)-(\w+)-(\w+(?:-\w+)*))\b,'); - -// Compatibilite pour 1.92 : on a besoin de sql_fetch et table_objet_sql -if ($GLOBALS['spip_version_code'] < '1.93' AND $f = charger_fonction('compat_crayons', 'inc')) - $f(); - -// Autoriser les crayons sur les tables non SPIP ? -// Par defaut : oui (pour les admins complets, si autoriser_defaut_dist()) ; -// mettre a false en cas de mutualisation par prefixe de table, -// sinon on ne peut pas garantir que les sites sont hermetiques -if(!defined('_CRAYONS_TABLES_EXTERNES')) - define('_CRAYONS_TABLES_EXTERNES', true); - -// Autorisations non prevues par le core -include_spip('inc/autoriser'); - -include_spip('inc/crayons-json'); - -if (!function_exists('autoriser_meta_modifier_dist')) { -/** - * Autorisation d'éditer les configurations dans spip_meta - * - * Les admins complets OK pour certains champs, - * Sinon, il faut être webmestre - * - * @note - * Attention sur les SPIP < 11515 (avant 04/2008) inc/autoriser - * passe seulement intval($id) alors qu'ici la cle est une chaine... - * - * @param string $faire Action demandée - * @param string $type Type d'objet sur lequel appliquer l'action - * @param int $id Identifiant de l'objet - * @param array $qui Description de l'auteur demandant l'autorisation - * @param array $opt Options de cette autorisation - * @return bool true s'il a le droit, false sinon -**/ -function autoriser_meta_modifier_dist($faire, $type, $id, $qui, $opt) { - // Certaines cles de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc}) - // $id = str_replace('__', '/', $id); - if (in_array("$id", array( - 'nom_site', 'slogan_site', 'descriptif_site', 'email_webmaster' - ))) - return autoriser('configurer', null, null, $qui); - else - return autoriser('webmestre', null, null, $qui); -} -} - -// table spip_messages, la c'est tout simplement non (peut mieux faire, -// mais c'est a voir dans le core/organiseur ou dans autorite) -if (defined('_DIR_PLUGIN_ORGANISEUR')) - include_spip('organiseur_autoriser'); -if (!function_exists('autoriser_message_modifier_dist')) { - function autoriser_message_modifier_dist($faire, $type, $id, $qui, $opt) { - return false; - } -} -//compat 192 documents -if ($GLOBALS['spip_version_code'] < '1.93'){ - if (!function_exists('get_spip_doc')){ - function get_spip_doc($fichier) { - // fichier distant - if (preg_match(',^\w+://,', $fichier)) - return $fichier; - - // gestion d'erreurs, fichier='' - if (!strlen($fichier)) - return false; - - // fichier normal - return (strpos($fichier, _DIR_IMG) === false) - ? _DIR_IMG . $fichier - : $fichier; - } - } -} - -// Autoriser l'usage des crayons ? -function autoriser_crayonner_dist($faire, $type, $id, $qui, $opt) { - // Le type pouvant etre une table, verifier les autoriser('modifier') - // correspondant ; ils demandent le nom de l'objet: spip_articles => article - // ex: spip_articles => 'article' - $type = preg_replace(',^spip_(.*?)s?$,', '\1', $type); - if (strlen($GLOBALS['table_prefix'])) - $type = preg_replace(',^'.$GLOBALS['table_prefix'].'_(.*?)s?$,', '\1', $type); - - // Tables non SPIP ? Si elles sont interdites il faut regarder - // quelle table on appelle, et verifier si elle est "interne" - if (!_CRAYONS_TABLES_EXTERNES) { - include_spip('base/serial'); - include_spip('base/auxiliaires'); - include_spip('public/parametrer'); - if (!isset($GLOBALS['tables_principales']['spip_'.table_objet($type)]) - AND !isset($GLOBALS['tables_auxiliaires']['spip_'.table_objet($type)])) - return false; - } - - // Traduire le modele en liste de champs - if (isset($opt['modele'])) - $opt['champ'] = $opt['modele']; - - // Pour un auteur, si le champ est statut ou email, signaler l'option - // ad hoc (cf. inc/autoriser) - if ($type == 'auteur' - AND in_array($opt['champ'], array('statut', 'email'))) - $opt[$opt['champ']] = true; - - return ( - autoriser('modifier', $type, $id, $qui, $opt) - ); -} - -// Si un logo est demande, on renvoie la date dudit logo (permettra de gerer -// un "modifie par ailleurs" si la date a change, rien de plus) -function valeur_champ_logo($table, $id, $champ) { - $chercher_logo = charger_fonction('chercher_logo', 'inc'); - $on = $chercher_logo($id, id_table_objet($table), 'on'); - return $on ? filemtime($on[0]) : false; -} - -// Idem : si un doc est demande, on renvoie la date du doc -function valeur_champ_document($table, $id, $champ) { - $s = spip_query("SELECT date FROM spip_documents WHERE id_document="._q($id)); - if ($t = sql_fetch($s)) - return $t['date']; -} - -function valeur_champ_vignette($table, $id, $champ) { - $vignette = sql_getfetsel('id_vignette','spip_documents','id_document='.intval($id)); - if(is_numeric($vignette) && ($vignette > 0)){ - $date = sql_getfetsel('date','spip_documents','id_document='.intval($vignette)); - } - return $date ? $date : false; -} -// cette fonction de revision recoit le fichier upload a passer en logo -// en reference : le nom du widget, pour aller chercher d'autres donnees -// (ex: supprimer) -function logo_revision($id, $file, $type, $ref) { - $chercher_logo = charger_fonction('chercher_logo', 'inc'); - $_id_objet = id_table_objet($type); - - // Chargement d'un nouveau logo ? - if ($file['logo']) { - define('FILE_UPLOAD', true); // message pour crayons_json_export :( - - // supprimer l'ancien logo - $on = $chercher_logo($id, $_id_objet, 'on'); - if ($on) @unlink($on[0]); - - // ajouter le nouveau - include_spip('action/iconifier'); - action_spip_image_ajouter_dist( - type_du_logo($_id_objet).'on'.$id, false, false - ); // beurk - } - - else - - // Suppression du logo ? - if ($wid = array_pop($ref) - AND $_POST['content_'.$wid.'_logo_supprimer'] == 'on') { - if ($on = $chercher_logo($id, $_id_objet, 'on')) - @unlink($on[0]); - } - - // Reduire le logo ? - if (is_array($cfg = @unserialize($GLOBALS['meta']['crayons'])) - AND $max = intval($cfg['reduire_logo'])) { - $on = $chercher_logo($id, $_id_objet, 'on'); - include_spip('inc/filtres'); - @copy($on[0], $temp = _DIR_VAR.'tmp'.rand(0,999).'.'.$on[3]); - $img1 = filtrer('image_reduire', $temp, $max); - $img2 = preg_replace(',[?].*,', '', extraire_attribut($img1, 'src')); - if (@file_exists($img2) - AND $img2 != $temp) { - @unlink($on[0]); - $dest = $on[1].$on[2].'.' - .preg_replace(',^.*\.(gif|jpg|png)$,', '\1', $img2); - @rename($img2,$dest); - } - @unlink($temp); - } - - return true; -} - - -// cette fonction de revision recoit le fichier upload a passer en document -function document_fichier_revision($id, $data, $type, $ref) { - - $s = spip_query("SELECT * FROM spip_documents WHERE id_document=".intval($id)); - if (!$t = sql_fetch($s)) - return false; - - /* - // Envoi d'une URL de document distant ? - // TODO: verifier l'extension distante, sinon tout explose - if ($data['fichier'] - AND preg_match(',^(https?|ftp)://.+,', $data['fichier'])) { - include_spip('inc/modifier'); - modifier_contenu('document', $id, - array('champs' => array('fichier', 'distant')), - array('fichier' => $data['fichier'], 'distant' => 'oui') - ); - return true; - } - else - */ - - // Chargement d'un nouveau doc ? - if ($data['document']) { - - $arg = $data['document']; - - /** - * Méthode >= SPIP 3.0 - * ou SPIP 2.x + Mediathèque - */ - if($ajouter_documents = charger_fonction('ajouter_documents','action',true)){ - $actifs = $ajouter_documents($id,array($arg),'', 0,$t['mode']); - $x = reset($actifs); - if(is_numeric($x)) - return true; - else - return false; - } - /** - * Méthode SPIP < 3.0 - */ - else if($ajouter_documents = charger_fonction('ajouter_documents','inc',true)){ - check_upload_error($arg['error']); - $x = $ajouter_documents($arg['tmp_name'], $arg['name'], - 'article', 0, 'document', null, $actifs); - // $actifs contient l'id_document nouvellement cree - // on recopie les donnees interessantes dans l'ancien - $extension=", extension "; - //compat 192 - if ($GLOBALS['spip_version_code'] < '1.93') - $extension=""; - - if ($id_new = array_pop($actifs) - AND $s = spip_query("SELECT fichier, taille, largeur, hauteur $extension, distant FROM spip_documents - WHERE id_document="._q($id_new)) - AND $new = sql_fetch($s)) { - define('FILE_UPLOAD', true); // message pour crayons_json_export :( - - // Une vignette doit rester une image - if ($t['mode'] == 'vignette' - AND !in_array($new['extension'], array('jpg', 'gif', 'png'))) - return false; - - // Maintenant on est bon, on recopie les nouvelles donnees - // dans l'ancienne ligne spip_documents - include_spip('inc/modifier'); - modifier_contenu('document', $id, - # 'champs' inutile a partir de SPIP 11348 - array('champs' => array_keys($new)), - $new); - - // supprimer l'ancien document (sauf s'il etait distant) - if ($t['distant'] != 'oui' - AND file_exists(get_spip_doc($t['fichier']))) - supprimer_fichier(get_spip_doc($t['fichier'])); - - // Effacer la ligne temporaire de spip_document - spip_query("DELETE FROM spip_documents WHERE id_document="._q($id_new)); - - // oublier id_document temporaire (ca marche chez moi, sinon bof) - spip_query("ALTER TABLE spip_documents AUTO_INCREMENT="._q($id_new)); - - return true; - } - } - } -} - -// cette fonction de revision soit supprime la vignette d'un document, -// soit recoit le fichier upload a passer ou remplacer la vignette du document -function vignette_revision($id, $data, $type, $ref) { - $s = sql_fetsel("id_document,id_vignette","spip_documents","id_document=".intval($id)); - if (!is_array($s)) - return false; - - include_spip('inc/modifier'); - include_spip('inc/documents'); - include_spip('action/editer_document');//pour revision_document - // Chargement d'un nouveau doc ? - if ($data['vignette']) { - define('FILE_UPLOAD', true); - if(is_numeric($s['id_vignette']) && ($s['id_vignette']>0)){ - spip_log('suppression de la vignette'); - // Suppression du document - $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette'])); - if (@file_exists($f = get_spip_doc($vignette))) { - spip_log("efface $f"); - supprimer_fichier($f); - } - sql_delete('spip_documents', 'id_document='.intval($s['id_vignette'])); - sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette'])); - - pipeline('post_edition', - array( - 'args' => array( - 'operation' => 'supprimer_document', - 'table' => 'spip_documents', - 'id_objet' => $s['id_vignette'] - ), - 'data' => null - ) - ); - $id_vignette = 0; - } - - $arg = $data['vignette']; - check_upload_error($arg['error']); - // Ajout du document comme vignette - - /** - * Méthode >= SPIP 3.0 - * ou SPIP 2.x + Mediatheque - */ - if($ajouter_documents = charger_fonction('ajouter_documents','action',true)){ - $x = $ajouter_documents(null,array($arg),'', 0, 'vignette'); - $vignette = reset($x); - if(intval($vignette)) - document_modifier($id, array('id_vignette'=>$vignette)); - else if($id_vignette) - document_modifier($id, array('id_vignette'=>$id_vignette)); - } - /** - * Méthode < SPIP 3.0 - */ - else if($ajouter_documents = charger_fonction('ajouter_documents','inc',true)){ - // On remet l'id_vignette a 0 si on l'a supprimé - if($id_vignette) revision_document($s['id_document'], array('id_vignette'=>0)); - $x = $ajouter_documents($arg['tmp_name'], $arg['name'],'','', 'vignette', $id, $actifs); - } - - }else - // Suppression de la vignette ? - if ($wid = array_pop($ref) - AND $_POST['content_'.$wid.'_vignette_supprimer'] == 'on') { - if(is_numeric($s['id_vignette']) && ($s['id_vignette']>0)){ - // Suppression du document - $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette'])); - if (@file_exists($f = get_spip_doc($vignette))) { - spip_log("efface $f"); - supprimer_fichier($f); - } - sql_delete('spip_documents', 'id_document='.intval($s['id_vignette'])); - sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette'])); - - pipeline('post_edition', - array( - 'args' => array( - 'operation' => 'supprimer_document', - 'table' => 'spip_documents', - 'id_objet' => $s['id_vignette'] - ), - 'data' => null - ) - ); - - // On remet l'id_vignette a 0 - revision_document($s['id_document'], array('id_vignette'=>0)); - } - } - return true; -} - - -function colonne_table($type, $col) { - list($distant,$table) = distant_table($type); - $nom_table = ''; - if (!(($tabref = &crayons_get_table($table, $nom_table)) - && isset($tabref['field'][$col]) - && ($brut = $tabref['field'][$col]))) { - return false; - } - $ana = explode(' ', $brut); - $sta = 0; - $sep = ''; - $ret = array('brut' => $brut, - 'type' => '', 'notnull' => false, 'long' => 0, 'def' => ''); - foreach ($ana as $mot) { - switch ($sta) { - case 0: $ret['type'] = ($mot = strtolower($mot)); - case 1: if ($mot[strlen($mot) - 1] == ')') { - $pos = strpos($mot, '('); - $ret['type'] = strtolower(substr($mot, 0, $pos++)); - $vir = explode(',', substr($mot, $pos, -1)); - if ($ret['type'] == 'enum') { - $ret['enum'] = $vir; - } elseif (count($vir) > 1) { - $ret['long'] = $vir; - } else { - $ret['long'] = $vir[0]; - } - $sta = 1; - continue; - } - if (!$sta) { - $sta = 1; - continue; - } - case 2: switch (strtolower($mot)) { - case 'not': - $sta = 3; - continue; - case 'default': - $sta = 4; - continue; - } - continue; - case 3: $ret['notnull'] = strtolower($mot) == 'null'; - $sta = 2; - continue; - case 4: $df1 = strpos('"\'', $mot[0]) !== false? $mot[0] : ''; - $sta = 5; - case 5: $ret['def'] .= $sep . $mot; - if (!$df1) { - $sta = 2; - continue; - } - if ($df1 == $mot[strlen($mot) - 1]) { - $ret['def'] = substr($ret['def'], 1, -1); - $sta = 2; - } - $sep = ' '; - continue; - } - } - return $ret; -} - - -/** - * Obtient le nom de la table ainsi que sa ou ses clés primaires - * - * @param string $type - * Table sur laquelle s'applique le crayon. - * Ce type peut contenir le nom d'un connecteur distant tel que `{connect}__{table}` - * - * @return array|bool - * - false si on ne trouve pas de table ou de table ayant de clé primaire - * - liste : - * - - nom de la table sql - * - - tableau des noms de clés primaires -**/ -function crayons_get_table_name_and_primary($type) { - static $types = array(); - if (isset($types[$type])) { - return $types[$type]; - } - - $nom_table = ''; - if ($tabref = &crayons_get_table($type, $nom_table) - and ($tabid = explode(',', $tabref['key']['PRIMARY KEY']))) - { - return $types[$type] = array($nom_table, $tabid); - } - spip_log('crayons: table ' . $type . ' inconnue'); - return $types[$type] = false; -} - - -function table_where($type, $id, $where_en_tableau = false) { - - - if (!$infos = crayons_get_table_name_and_primary($type)) { - return array(false, false); - } - - list($nom_table, $tabid) = $infos; - - - if (is_scalar($id)) - $id = explode('-', $id); - // sortie tableau pour sql_updateq - if ($where_en_tableau) { - $where = array(); - foreach ($id as $idcol => $idval) { - $where[] = '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . sql_quote($idval); - } - // sinon sortie texte pour sql_query - } else { - - $where = $and = ''; - foreach ($id as $idcol => $idval) { - $where .= $and . '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . _q($idval); - $and = ' AND '; - } - } - return array($nom_table, $where); -} -// var_dump(colonne_table('forum', 'id_syndic')); die(); - -function valeur_colonne_table_dist($type, $col, $id) { - - // Table introuvable ou sans clé primaire - if (!$infos = crayons_get_table_name_and_primary($type)) { - return false; - } - $table = reset($infos); - - $r = array(); - - // valeurs non SQL - foreach ($col as $champ) { - if (function_exists($f = 'valeur_champ_'.$table.'_'.$champ) OR function_exists($f = 'valeur_champ_'.$champ)) { - $r[$champ] = $f($table, $id, $champ); - $col = array_diff($col, array($champ)); - } - } - - // valeurs SQL - if (count($col)) { - list($distant, $table) = distant_table($type); - list($nom_table, $where) = table_where($type, $id); - - if ($s = spip_query( - 'SELECT `' . implode($col, '`, `') . - '` FROM ' . $nom_table . ' WHERE ' . $where, $distant) - AND $t = sql_fetch($s)){ - $r = array_merge($r, $t); - } - } - - return $r; -} - -/** - * Extrait la valeur d'une ou plusieurs colonnes d'une table - * - * @param string $table - * Type d'objet de la table (article) - * @param string|array $col - * Nom de la ou des colonnes (ps) - * @param string $id - * Identifiant de l'objet - * @return array - * Couples Nom de la colonne => Contenu de la colonne -**/ -function valeur_colonne_table($table, $col, $id) { - if (!is_array($col)) - $col = array($col); - - if (function_exists($f = $table.'_valeur_colonne_table_dist') - OR function_exists($f = $table.'_valeur_colonne_table') - OR $f = 'valeur_colonne_table_dist') - return $f($table, $col, $id); -} - -/** - * Extrait la valeur d'une configuration en meta - * - * Pour ces données, il n'y a toujours qu'une colonne (valeur), - * mais on gère l'enregistrement et la lecture via lire_config ou ecrire_config - * dès que l'on demande des sous parties d'une configuration. - * - * On ne retourne alors ici dans 'valeur' que la sous-partie demandée si - * c'est le cas. - * - * @param string $table - * Nom de la table (meta) - * @param array $col - * Nom des colonnes (valeur) - * @param string $id - * Nom ou clé de configuration (descriptif_site ou demo__truc pour demo/truc) - * @return array - * Couple valeur => Contenu de la configuration -**/ -function meta_valeur_colonne_table_dist($table, $col, $id) { - // Certaines clés de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc}) - $id = str_replace('__', '/', $id); - - // Éviter de planter les vieux SPIP - if (false === strpos($id, '/')) { - $config = isset($GLOBALS['meta'][$id]) ? $GLOBALS['meta'][$id] : ''; - // SPIP 3 ou Bonux 2 ou CFG - } else { - include_spip('inc/config'); - $config = lire_config($id, ''); - } - return array('valeur' => $config); -} - - -function return_log($var) { - die(crayons_json_export(array('$erreur'=> var_export($var,true)))); -} - -function _U($texte, $params=array()) { - include_spip('inc/charsets'); - return unicode2charset(html2unicode(_T($texte, $params))); -} - -/** - * Obtenir la configuration des crayons - * - * @note wdgcfg = widget config :-) - * - * @return array - * Couples : attribut => valeur -**/ -function wdgcfg() { - $php = function_exists('crayons_config') ? crayons_config() : array(); - include_spip('inc/meta'); - lire_metas(); - global $meta; - $metacrayons = empty($meta['crayons']) ? array() : unserialize($meta['crayons']); - $wdgcfg = array(); - foreach (array( - 'msgNoChange' => false, - 'msgAbandon' => false, /* etait: true */ - 'filet' => false, - 'yellow_fade' => false, - 'clickhide' => false /* etait: true */ - ) - as $cfgi => $def) { - $wdgcfg[$cfgi] = isset($php[$cfgi]) ? $php[$cfgi] : - isset($metacrayons[$cfgi]) ? $metacrayons[$cfgi] : $def; - } - return $wdgcfg; -} - -function &crayons_get_table($type, &$nom_table) { - list($distant,$table) = distant_table($type); - static $return = array(); - static $noms = array(); - if (!isset($return[$table])) { - $try = array(table_objet_sql($table), 'spip_'.table_objet($table), 'spip_' . $table . 's', $table . 's', 'spip_' . $table, $table); - - // premiere possibilite (à partir de 1.9.3) : regarder directement la base - if (function_exists('sql_showtable')) { - foreach ($try as $nom) { - if ($q = sql_showtable($nom , !$distant , $distant)) { - $noms[$table] = $nom; - $return[$table] = $q; - break; - } - } - } - - // seconde, une heuristique 1.9.2 - if (!isset($return[$table])) { - include_spip('base/serial'); - include_spip('base/auxiliaires'); - include_spip('public/parametrer'); - foreach(array('tables_principales', 'tables_auxiliaires') as $categ) { - foreach ($try as $nom) { - if (isset($GLOBALS[$categ][$nom])) { - $noms[$table] = $nom; - $return[$table] = & $GLOBALS[$categ][$nom]; - break 2; - } - } - } - } - } - - $nom_table = $noms[$table]; - return $return[$table]; -} - -function distant_table($type) { - //separation $type en $distant $table - //separateur double underscore "__" - strstr($type,'__')? list($distant,$table) = explode('__',$type) : list($distant,$table) = array(False,$type); - return array($distant,$table); -} -?> +\'"]+?\b((\w+)-(\w+)-(\w+(?:-\w+)*))\b,'); + +// Compatibilite pour 1.92 : on a besoin de sql_fetch et table_objet_sql +if ($GLOBALS['spip_version_code'] < '1.93' and $f = charger_fonction('compat_crayons', 'inc')) { + $f(); +} + +// Autoriser les crayons sur les tables non SPIP ? +// Par defaut : oui (pour les admins complets, si autoriser_defaut_dist()) ; +// mettre a false en cas de mutualisation par prefixe de table, +// sinon on ne peut pas garantir que les sites sont hermetiques +if (!defined('_CRAYONS_TABLES_EXTERNES')) { + define('_CRAYONS_TABLES_EXTERNES', true); +} + +// Autorisations non prevues par le core +include_spip('inc/autoriser'); + +include_spip('inc/crayons-json'); + +if (!function_exists('autoriser_meta_modifier_dist')) { +/** + * Autorisation d'éditer les configurations dans spip_meta + * + * Les admins complets OK pour certains champs, + * Sinon, il faut être webmestre + * + * @note + * Attention sur les SPIP < 11515 (avant 04/2008) inc/autoriser + * passe seulement intval($id) alors qu'ici la cle est une chaine... + * + * @param string $faire Action demandée + * @param string $type Type d'objet sur lequel appliquer l'action + * @param int $id Identifiant de l'objet + * @param array $qui Description de l'auteur demandant l'autorisation + * @param array $opt Options de cette autorisation + * @return bool true s'il a le droit, false sinon +**/ +function autoriser_meta_modifier_dist($faire, $type, $id, $qui, $opt) { + // Certaines cles de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc}) + // $id = str_replace('__', '/', $id); + if (in_array($id, array('nom_site', 'slogan_site', 'descriptif_site', 'email_webmaster'))) { + return autoriser('configurer', null, null, $qui); + } else { + return autoriser('webmestre', null, null, $qui); + } +} +} + +// table spip_messages, la c'est tout simplement non (peut mieux faire, +// mais c'est a voir dans le core/organiseur ou dans autorite) +if (defined('_DIR_PLUGIN_ORGANISEUR')) { + include_spip('organiseur_autoriser'); +} + +if (!function_exists('autoriser_message_modifier_dist')) { + function autoriser_message_modifier_dist($faire, $type, $id, $qui, $opt) { + return false; + } +} +//compat 192 documents +if ($GLOBALS['spip_version_code'] < '1.93') { + if (!function_exists('get_spip_doc')) { + function get_spip_doc($fichier) { + // fichier distant + if (preg_match(',^\w+://,', $fichier)) { + return $fichier; + } + // gestion d'erreurs, fichier='' + if (!strlen($fichier)) { + return false; + } + + // fichier normal + return (strpos($fichier, _DIR_IMG) === false) ? _DIR_IMG . $fichier : $fichier; + } + } +} + +// Autoriser l'usage des crayons ? +function autoriser_crayonner_dist($faire, $type, $id, $qui, $opt) { + // Le type pouvant etre une table, verifier les autoriser('modifier') + // correspondant ; ils demandent le nom de l'objet: spip_articles => article + // ex: spip_articles => 'article' + $type = preg_replace(',^spip_(.*?)s?$,', '\1', $type); + if (strlen($GLOBALS['table_prefix'])) { + $type = preg_replace(',^'.$GLOBALS['table_prefix'].'_(.*?)s?$,', '\1', $type); + } + + // Tables non SPIP ? Si elles sont interdites il faut regarder + // quelle table on appelle, et verifier si elle est "interne" + if (!_CRAYONS_TABLES_EXTERNES) { + include_spip('base/serial'); + include_spip('base/auxiliaires'); + include_spip('public/parametrer'); + if (!isset($GLOBALS['tables_principales']['spip_'.table_objet($type)]) + and !isset($GLOBALS['tables_auxiliaires']['spip_'.table_objet($type)])) { + return false; + } + } + + // Traduire le modele en liste de champs + if (isset($opt['modele'])) { + $opt['champ'] = $opt['modele']; + } + + // Pour un auteur, si le champ est statut ou email, signaler l'option + // ad hoc (cf. inc/autoriser) + if ($type == 'auteur' + and in_array($opt['champ'], array('statut', 'email'))) { + $opt[$opt['champ']] = true; + } + + return ( + autoriser('modifier', $type, $id, $qui, $opt) + ); +} + +// Si un logo est demande, on renvoie la date dudit logo (permettra de gerer +// un "modifie par ailleurs" si la date a change, rien de plus) +function valeur_champ_logo($table, $id, $champ) { + $chercher_logo = charger_fonction('chercher_logo', 'inc'); + $on = $chercher_logo($id, id_table_objet($table), 'on'); + return $on ? filemtime($on[0]) : false; +} + +// Idem : si un doc est demande, on renvoie la date du doc +function valeur_champ_document($table, $id, $champ) { + $s = spip_query('SELECT date FROM spip_documents WHERE id_document=' . _q($id)); + if ($t = sql_fetch($s)) { + return $t['date']; + } +} + +function valeur_champ_vignette($table, $id, $champ) { + $vignette = sql_getfetsel('id_vignette', 'spip_documents', 'id_document=' . intval($id)); + if (is_numeric($vignette) && ($vignette > 0)) { + $date = sql_getfetsel('date', 'spip_documents', 'id_document=' . intval($vignette)); + } + return $date ? $date : false; +} +// cette fonction de revision recoit le fichier upload a passer en logo +// en reference : le nom du widget, pour aller chercher d'autres donnees +// (ex: supprimer) +function logo_revision($id, $file, $type, $ref) { + $chercher_logo = charger_fonction('chercher_logo', 'inc'); + $_id_objet = id_table_objet($type); + + // Chargement d'un nouveau logo ? + if ($file['logo']) { + define('FILE_UPLOAD', true); // message pour crayons_json_export :( + + if (include_spip('action/editer_logo') + and function_exists('logo_modifier')) { + logo_modifier($type, $id, 'on', $file['logo']); + } else { + // compat SPIP < 3.1 + // supprimer l'ancien logo + $on = $chercher_logo($id, $_id_objet, 'on'); + if ($on) { + @unlink($on[0]); + } + + // ajouter le nouveau + include_spip('action/iconifier'); + action_spip_image_ajouter_dist(type_du_logo($_id_objet) . 'on' . $id, false, false); // beurk + } + } else { + // Suppression du logo ? + if ($wid = array_pop($ref) + and $_POST['content_'.$wid.'_logo_supprimer'] == 'on') { + if (include_spip('action/editer_logo') + and function_exists('logo_supprimer')) { + logo_supprimer($type, $id, 'on'); + } else { + if ($on = $chercher_logo($id, $_id_objet, 'on')) { + @unlink($on[0]); + } + } + } + } + + // Reduire le logo ? + if (is_array($cfg = @unserialize($GLOBALS['meta']['crayons'])) + and $max = intval($cfg['reduire_logo'])) { + $on = $chercher_logo($id, $_id_objet, 'on'); + include_spip('inc/filtres'); + @copy($on[0], $temp = _DIR_VAR . 'tmp' . rand(0, 999) . '.' . $on[3]); + $img1 = filtrer('image_reduire', $temp, $max); + $img2 = preg_replace(',[?].*,', '', extraire_attribut($img1, 'src')); + if (@file_exists($img2) + and $img2 != $temp) { + if (include_spip('action/editer_logo') + and function_exists('logo_modifier')) { + logo_modifier($type, $id, 'on', $img2); + } else { + @unlink($on[0]); + $dest = $on[1].$on[2].'.' + .preg_replace(',^.*\.(gif|jpg|png)$,', '\1', $img2); + @rename($img2, $dest); + } + } + @unlink($temp); + } + + return true; +} + + +// cette fonction de revision recoit le fichier upload a passer en document +function document_fichier_revision($id, $data, $type, $ref) { + + $s = spip_query('SELECT * FROM spip_documents WHERE id_document=' . intval($id)); + if (!$t = sql_fetch($s)) { + return false; + } + + /* + // Envoi d'une URL de document distant ? + // TODO: verifier l'extension distante, sinon tout explose + if ($data['fichier'] + AND preg_match(',^(https?|ftp)://.+,', $data['fichier'])) { + include_spip('inc/modifier'); + modifier_contenu('document', $id, + array('champs' => array('fichier', 'distant')), + array('fichier' => $data['fichier'], 'distant' => 'oui') + ); + return true; + } + else + */ + + // Chargement d'un nouveau doc ? + if ($data['document']) { + $arg = $data['document']; + /** + * Méthode >= SPIP 3.0 + * ou SPIP 2.x + Mediathèque + */ + if ($ajouter_documents = charger_fonction('ajouter_documents', 'action', true)) { + $actifs = $ajouter_documents($id, array($arg), '', 0, $t['mode']); + $x = reset($actifs); + if (is_numeric($x)) { + return true; + } else { + return false; + } + } elseif ($ajouter_documents = charger_fonction('ajouter_documents', 'inc', true)) { + /** + * Méthode SPIP < 3.0 + */ + check_upload_error($arg['error']); + $x = $ajouter_documents($arg['tmp_name'], $arg['name'], + 'article', 0, 'document', null, $actifs); + // $actifs contient l'id_document nouvellement cree + // on recopie les donnees interessantes dans l'ancien + $extension = ', extension '; + //compat 192 + if ($GLOBALS['spip_version_code'] < '1.93') { + $extension = ''; + } + + if ($id_new = array_pop($actifs) + and $s = spip_query("SELECT fichier, taille, largeur, hauteur $extension, distant FROM spip_documents + WHERE id_document="._q($id_new)) + and $new = sql_fetch($s)) { + define('FILE_UPLOAD', true); // message pour crayons_json_export :( + + // Une vignette doit rester une image + if ($t['mode'] == 'vignette' + and !in_array($new['extension'], array('jpg', 'gif', 'png'))) { + return false; + } + + // Maintenant on est bon, on recopie les nouvelles donnees + // dans l'ancienne ligne spip_documents + include_spip('inc/modifier'); + modifier_contenu( + 'document', + $id, + # 'champs' inutile a partir de SPIP 11348 + array('champs' => array_keys($new)), + $new + ); + + // supprimer l'ancien document (sauf s'il etait distant) + if ($t['distant'] != 'oui' + and file_exists(get_spip_doc($t['fichier']))) { + supprimer_fichier(get_spip_doc($t['fichier'])); + } + + // Effacer la ligne temporaire de spip_document + spip_query('DELETE FROM spip_documents WHERE id_document='.intval($id_new)); + + // oublier id_document temporaire (ca marche chez moi, sinon bof) + spip_query('ALTER TABLE spip_documents AUTO_INCREMENT='.intval($id_new)); + + return true; + } + } + } +} + +// cette fonction de revision soit supprime la vignette d'un document, +// soit recoit le fichier upload a passer ou remplacer la vignette du document +function vignette_revision($id, $data, $type, $ref) { + $s = sql_fetsel('id_document,id_vignette', 'spip_documents', 'id_document = '.intval($id)); + if (!is_array($s)) { + return false; + } + + include_spip('inc/modifier'); + include_spip('inc/documents'); + include_spip('action/editer_document');//pour revision_document + // Chargement d'un nouveau doc ? + if ($data['vignette']) { + define('FILE_UPLOAD', true); + if (is_numeric($s['id_vignette']) and ($s['id_vignette'] > 0)) { + spip_log('suppression de la vignette'); + // Suppression du document + $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette'])); + if (@file_exists($f = get_spip_doc($vignette))) { + spip_log("efface $f"); + supprimer_fichier($f); + } + sql_delete('spip_documents', 'id_document='.intval($s['id_vignette'])); + sql_delete('spip_documents_liens', 'id_document='.intval($s['id_vignette'])); + + pipeline( + 'post_edition', + array( + 'args' => array( + 'operation' => 'supprimer_document', + 'table' => 'spip_documents', + 'id_objet' => $s['id_vignette'] + ), + 'data' => null + ) + ); + $id_vignette = 0; + } + + $arg = $data['vignette']; + check_upload_error($arg['error']); + // Ajout du document comme vignette + + /** + * Méthode >= SPIP 3.0 + * ou SPIP 2.x + Mediatheque + */ + if ($ajouter_documents = charger_fonction('ajouter_documents', 'action', true)) { + $x = $ajouter_documents(null,array($arg),'', 0, 'vignette'); + $vignette = reset($x); + if (intval($vignette)) { + document_modifier($id, array('id_vignette'=>$vignette)); + } elseif ($id_vignette) { + document_modifier($id, array('id_vignette'=>$id_vignette)); + } + } elseif ($ajouter_documents = charger_fonction('ajouter_documents', 'inc', true)) { + /** + * Méthode < SPIP 3.0 + */ + // On remet l'id_vignette a 0 si on l'a supprimé + if ($id_vignette) { + revision_document($s['id_document'], array('id_vignette' => 0)); + } + $x = $ajouter_documents($arg['tmp_name'], $arg['name'],'','', 'vignette', $id, $actifs); + } + } elseif ($wid = array_pop($ref) + and $_POST['content_'.$wid.'_vignette_supprimer'] == 'on') { + if (is_numeric($s['id_vignette']) and ($s['id_vignette']>0)) { + // Suppression du document + $vignette = sql_getfetsel('fichier', 'spip_documents', 'id_document='.intval($s['id_vignette'])); + if (@file_exists($f = get_spip_doc($vignette))) { + spip_log("efface $f"); + supprimer_fichier($f); + } + sql_delete('spip_documents', 'id_document='.intval($s['id_vignette'])); + sql_delete('spip_documents_liens', 'id_document = ' . intval($s['id_vignette'])); + + pipeline( + 'post_edition', + array( + 'args' => array( + 'operation' => 'supprimer_document', + 'table' => 'spip_documents', + 'id_objet' => $s['id_vignette'] + ), + 'data' => null + ) + ); + + // On remet l'id_vignette a 0 + revision_document($s['id_document'], array('id_vignette'=>0)); + } + } + return true; +} + + +function colonne_table($type, $col) { + list($distant,$table) = distant_table($type); + $nom_table = ''; + if (!(($tabref = &crayons_get_table($table, $nom_table)) + && isset($tabref['field'][$col]) + && ($brut = $tabref['field'][$col]))) { + return false; + } + $ana = explode(' ', $brut); + $sta = 0; + $sep = ''; + $ret = array('brut' => $brut, + 'type' => '', 'notnull' => false, 'long' => 0, 'def' => ''); + foreach ($ana as $mot) { + switch ($sta) { + case 0: + $ret['type'] = ($mot = strtolower($mot)); + continue; + case 1: + if ($mot[strlen($mot) - 1] == ')') { + $pos = strpos($mot, '('); + $ret['type'] = strtolower(substr($mot, 0, $pos++)); + $vir = explode(',', substr($mot, $pos, -1)); + if ($ret['type'] == 'enum') { + $ret['enum'] = $vir; + } elseif (count($vir) > 1) { + $ret['long'] = $vir; + } else { + $ret['long'] = $vir[0]; + } + $sta = 1; + continue; + } + if (!$sta) { + $sta = 1; + continue; + } + continue; + case 2: + switch (strtolower($mot)) { + case 'not': + $sta = 3; + continue; + case 'default': + $sta = 4; + continue; + } + continue; + case 3: + $ret['notnull'] = strtolower($mot) == 'null'; + $sta = 2; + continue; + case 4: + $df1 = strpos('"\'', $mot[0]) !== false? $mot[0] : ''; + $sta = 5; + continue; + case 5: + $ret['def'] .= $sep . $mot; + if (!$df1) { + $sta = 2; + continue; + } + if ($df1 == $mot[strlen($mot) - 1]) { + $ret['def'] = substr($ret['def'], 1, -1); + $sta = 2; + } + $sep = ' '; + continue; + } + } + return $ret; +} + + +/** + * Obtient le nom de la table ainsi que sa ou ses clés primaires + * + * @param string $type + * Table sur laquelle s'applique le crayon. + * Ce type peut contenir le nom d'un connecteur distant tel que `{connect}__{table}` + * + * @return array|bool + * - false si on ne trouve pas de table ou de table ayant de clé primaire + * - liste : + * - - nom de la table sql + * - - tableau des noms de clés primaires +**/ +function crayons_get_table_name_and_primary($type) { + static $types = array(); + if (isset($types[$type])) { + return $types[$type]; + } + + $nom_table = ''; + if ($tabref = &crayons_get_table($type, $nom_table) + and ($tabid = explode(',', $tabref['key']['PRIMARY KEY']))) { + return $types[$type] = array($nom_table, $tabid); + } + spip_log('crayons: table ' . $type . ' inconnue'); + return $types[$type] = false; +} + + +function table_where($type, $id, $where_en_tableau = false) { + if (!$infos = crayons_get_table_name_and_primary($type)) { + return array(false, false); + } + + list($nom_table, $tabid) = $infos; + + if (is_scalar($id)) { + $id = explode('-', $id); + } + // sortie tableau pour sql_updateq + if ($where_en_tableau) { + $where = array(); + foreach ($id as $idcol => $idval) { + $where[] = '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . sql_quote($idval); + } + // sinon sortie texte pour sql_query + } else { + $where = $and = ''; + foreach ($id as $idcol => $idval) { + $where .= $and . '`' . (is_int($idcol) ? trim($tabid[$idcol]) : $idcol) . '`=' . _q($idval); + $and = ' AND '; + } + } + return array($nom_table, $where); +} +// var_dump(colonne_table('forum', 'id_syndic')); die(); + +function valeur_colonne_table_dist($type, $col, $id) { + + // Table introuvable ou sans clé primaire + if (!$infos = crayons_get_table_name_and_primary($type)) { + return false; + } + $table = reset($infos); + + $r = array(); + + // valeurs non SQL + foreach ($col as $champ) { + if (function_exists($f = 'valeur_champ_'.$table.'_'.$champ) + or function_exists($f = 'valeur_champ_'.$champ)) { + $r[$champ] = $f($table, $id, $champ); + $col = array_diff($col, array($champ)); + } + } + + // valeurs SQL + if (count($col)) { + list($distant, $table) = distant_table($type); + list($nom_table, $where) = table_where($type, $id); + + if ($s = spip_query( + 'SELECT `' . implode($col, '`, `') . + '` FROM ' . $nom_table . ' WHERE ' . $where, + $distant + ) and $t = sql_fetch($s)) { + $r = array_merge($r, $t); + } + } + + return $r; +} + +/** + * Extrait la valeur d'une ou plusieurs colonnes d'une table + * + * @param string $table + * Type d'objet de la table (article) + * @param string|array $col + * Nom de la ou des colonnes (ps) + * @param string $id + * Identifiant de l'objet + * @return array + * Couples Nom de la colonne => Contenu de la colonne +**/ +function valeur_colonne_table($table, $col, $id) { + if (!is_array($col)) { + $col = array($col); + } + + if (function_exists($f = $table . '_valeur_colonne_table_dist') + or function_exists($f = $table.'_valeur_colonne_table') + or $f = 'valeur_colonne_table_dist') { + return $f($table, $col, $id); + } +} + +/** + * Extrait la valeur d'une configuration en meta + * + * Pour ces données, il n'y a toujours qu'une colonne (valeur), + * mais on gère l'enregistrement et la lecture via lire_config ou ecrire_config + * dès que l'on demande des sous parties d'une configuration. + * + * On ne retourne alors ici dans 'valeur' que la sous-partie demandée si + * c'est le cas. + * + * @param string $table + * Nom de la table (meta) + * @param array $col + * Nom des colonnes (valeur) + * @param string $id + * Nom ou clé de configuration (descriptif_site ou demo__truc pour demo/truc) + * @return array + * Couple valeur => Contenu de la configuration +**/ +function meta_valeur_colonne_table_dist($table, $col, $id) { + // Certaines clés de configuration sont echapées ici (cf #EDIT_CONFIG{demo/truc}) + $id = str_replace('__', '/', $id); + + // Éviter de planter les vieux SPIP + if (false === strpos($id, '/')) { + $config = isset($GLOBALS['meta'][$id]) ? $GLOBALS['meta'][$id] : ''; + // SPIP 3 ou Bonux 2 ou CFG + } else { + include_spip('inc/config'); + $config = lire_config($id, ''); + } + return array('valeur' => $config); +} + + +function return_log($var) { + die(crayons_json_export(array('$erreur'=> var_export($var, true)))); +} + +function _U($texte, $params = array()) { + include_spip('inc/charsets'); + return unicode2charset(html2unicode(_T($texte, $params))); +} + +/** + * Obtenir la configuration des crayons + * + * @note wdgcfg = widget config :-) + * + * @return array + * Couples : attribut => valeur +**/ +function wdgcfg() { + $php = function_exists('crayons_config') ? crayons_config() : array(); + include_spip('inc/meta'); + lire_metas(); + global $meta; + $metacrayons = empty($meta['crayons']) ? array() : unserialize($meta['crayons']); + $wdgcfg = array(); + foreach (array( + 'msgNoChange' => false, + 'msgAbandon' => false, /* etait: true */ + 'filet' => false, + 'yellow_fade' => false, + 'clickhide' => false /* etait: true */ + ) as $cfgi => $def) { + $wdgcfg[$cfgi] = isset($php[$cfgi]) ? $php[$cfgi] : + isset($metacrayons[$cfgi]) ? $metacrayons[$cfgi] : $def; + } + return $wdgcfg; +} + +function &crayons_get_table($type, &$nom_table) { + list($distant,$table) = distant_table($type); + static $return = array(); + static $noms = array(); + if (!isset($return[$table])) { + $try = array(table_objet_sql($table), 'spip_'.table_objet($table), 'spip_' . $table . 's', $table . 's', 'spip_' . $table, $table); + + // premiere possibilite (à partir de 1.9.3) : regarder directement la base + if (function_exists('sql_showtable')) { + foreach ($try as $nom) { + if ($q = sql_showtable($nom, !$distant, $distant)) { + $noms[$table] = $nom; + $return[$table] = $q; + break; + } + } + } + + // seconde, une heuristique 1.9.2 + if (!isset($return[$table])) { + include_spip('base/serial'); + include_spip('base/auxiliaires'); + include_spip('public/parametrer'); + foreach (array('tables_principales', 'tables_auxiliaires') as $categ) { + foreach ($try as $nom) { + if (isset($GLOBALS[$categ][$nom])) { + $noms[$table] = $nom; + $return[$table] = & $GLOBALS[$categ][$nom]; + break 2; + } + } + } + } + } + + $nom_table = $noms[$table]; + return $return[$table]; +} + +function distant_table($type) { + //separation $type en $distant $table + //separateur double underscore "__" + strstr($type, '__') ? list($distant,$table) = explode('__', $type) : list($distant, $table) = array(false, $type); + return array($distant,$table); +} diff --git a/www/plugins/crayons/js/crayons.js b/www/plugins/crayons/js/crayons.js index 00300b50..713b8acb 100644 --- a/www/plugins/crayons/js/crayons.js +++ b/www/plugins/crayons/js/crayons.js @@ -114,10 +114,10 @@ $.fn.opencrayon = function(evt, percent) { 'h': $(this).height(), 'ww': (window.innerWidth ? window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.offsetWidth)), 'wh': (window.innerHeight ? window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.offsetHeight)), - 'em': $(this).px('fontSize'), // eviter un bug MSIE sur fontSize + 'em': $(this).css('fontSize'), // Bug de jquery resolu : http://bugs.jquery.com/ticket/760 'class': me.className, 'color': $(this).css('color'), - 'font-size': $(this).px('fontSize'), + 'font-size': $(this).css('fontSize'), 'font-family': $(this).css('fontFamily'), 'font-weight': $(this).css('fontWeight'), 'line-height': $(this).css('lineHeight'), @@ -166,7 +166,11 @@ $.fn.opencrayon = function(evt, percent) { .addClass('crayon-has') .find('>.crayon-icones') .attr('rel','crayon_'+id_crayon); - if ($.browser.msie) $(me).css({'zoom':1}); + // Detection IE sur sa capacite a gerer zoom : + // http://www.sitepoint.com/detect-css3-property-browser-support/ + if (document.createElement("detect").style.zoom === "") { + $(me).css({'zoom':1}); + } var pos = $(me).offset(); $('
        ') .css({ @@ -329,6 +333,12 @@ $.fn.activatecrayon = function(percent) { d[$('input.crayon-id', crayon).val()] ) .iconecrayon(); + + // Invalider des préchargements ajax + if (typeof jQuery.spip == 'object' && typeof jQuery.spip.preloaded_urls == 'object') { + jQuery.spip.preloaded_urls = {}; + } + // Declencher le onAjaxLoad normal de SPIP if (typeof jQuery.spip == 'object' && typeof jQuery.spip.triggerAjaxLoad == 'function') { jQuery.spip.triggerAjaxLoad(tous.get()); diff --git a/www/plugins/crayons/js/jquery.form.js b/www/plugins/crayons/js/jquery.form.js index c0fba53c..591ad6f1 100644 --- a/www/plugins/crayons/js/jquery.form.js +++ b/www/plugins/crayons/js/jquery.form.js @@ -1,469 +1,836 @@ /*! * jQuery Form Plugin - * version: 2.73 (03-MAY-2011) - * @requires jQuery v1.3.2 or later - * + * version: 3.51.0-2014.06.20 + * Requires jQuery v1.5 or later + * Copyright (c) 2014 M. Alsup * Examples and documentation at: http://malsup.com/jquery/form/ - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html + * Project repository: https://github.com/malsup/form + * Dual licensed under the MIT and GPL licenses. + * https://github.com/malsup/form#copyright-and-license */ -;(function($) { +/*global ActiveXObject */ + +// AMD support +(function (factory) { + "use strict"; + if (typeof define === 'function' && define.amd) { + // using AMD; register as anon module + define(['jquery'], factory); + } else { + // no AMD; invoke directly + factory( (typeof(jQuery) != 'undefined') ? jQuery : window.Zepto ); + } +} + +(function($) { +"use strict"; /* - Usage Note: - ----------- - Do not use both ajaxSubmit and ajaxForm on the same form. These - functions are intended to be exclusive. Use ajaxSubmit if you want - to bind your own submit handler to the form. For example, - - $(document).ready(function() { - $('#myForm').bind('submit', function(e) { - e.preventDefault(); // <-- important - $(this).ajaxSubmit({ - target: '#output' - }); - }); - }); - - Use ajaxForm when you want the plugin to manage all the event binding - for you. For example, - - $(document).ready(function() { - $('#myForm').ajaxForm({ - target: '#output' - }); - }); - - When using ajaxForm, the ajaxSubmit function will be invoked for you - at the appropriate time. + Usage Note: + ----------- + Do not use both ajaxSubmit and ajaxForm on the same form. These + functions are mutually exclusive. Use ajaxSubmit if you want + to bind your own submit handler to the form. For example, + + $(document).ready(function() { + $('#myForm').on('submit', function(e) { + e.preventDefault(); // <-- important + $(this).ajaxSubmit({ + target: '#output' + }); + }); + }); + + Use ajaxForm when you want the plugin to manage all the event binding + for you. For example, + + $(document).ready(function() { + $('#myForm').ajaxForm({ + target: '#output' + }); + }); + + You can also use ajaxForm with delegation (requires jQuery v1.7+), so the + form does not have to exist when you invoke ajaxForm: + + $('#myForm').ajaxForm({ + delegation: true, + target: '#output' + }); + + When using ajaxForm, the ajaxSubmit function will be invoked for you + at the appropriate time. */ +/** + * Feature detection + */ +var feature = {}; +feature.fileapi = $("").get(0).files !== undefined; +feature.formdata = window.FormData !== undefined; + +var hasProp = !!$.fn.prop; + +// attr2 uses prop when it can but checks the return type for +// an expected string. this accounts for the case where a form +// contains inputs with names like "action" or "method"; in those +// cases "prop" returns the element +$.fn.attr2 = function() { + if ( ! hasProp ) { + return this.attr.apply(this, arguments); + } + var val = this.prop.apply(this, arguments); + if ( ( val && val.jquery ) || typeof val === 'string' ) { + return val; + } + return this.attr.apply(this, arguments); +}; + /** * ajaxSubmit() provides a mechanism for immediately submitting * an HTML form using AJAX. */ $.fn.ajaxSubmit = function(options) { - // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) - if (!this.length) { - log('ajaxSubmit: skipping submit process - no element selected'); - return this; - } - - if (typeof options == 'function') { - options = { success: options }; - } - - var action = this.attr('action'); - var url = (typeof action === 'string') ? $.trim(action) : ''; - if (url) { - // clean url (don't include hash vaue) - url = (url.match(/^([^#]+)/)||[])[1]; - } - url = url || window.location.href || ''; - - options = $.extend(true, { - url: url, - success: $.ajaxSettings.success, - type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57) - iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' - }, options); - - // hook for manipulating the form data before it is extracted; - // convenient for use with rich editors like tinyMCE or FCKEditor - var veto = {}; - this.trigger('form-pre-serialize', [this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); - return this; - } - - // provide opportunity to alter form data before it is serialized - if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSerialize callback'); - return this; - } - - var n,v,a = this.formToArray(options.semantic); - if (options.data) { - options.extraData = options.data; - for (n in options.data) { - if(options.data[n] instanceof Array) { - for (var k in options.data[n]) { - a.push( { name: n, value: options.data[n][k] } ); - } - } - else { - v = options.data[n]; - v = $.isFunction(v) ? v() : v; // if value is fn, invoke it - a.push( { name: n, value: v } ); - } - } - } - - // give pre-submit callback an opportunity to abort the submit - if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { - log('ajaxSubmit: submit aborted via beforeSubmit callback'); - return this; - } - - // fire vetoable 'validate' event - this.trigger('form-submit-validate', [a, this, options, veto]); - if (veto.veto) { - log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); - return this; - } - - var q = $.param(a); - - if (options.type.toUpperCase() == 'GET') { - options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; - options.data = null; // data is null for 'get' - } - else { - options.data = q; // data is the query string for 'post' - } - - var $form = this, callbacks = []; - if (options.resetForm) { - callbacks.push(function() { $form.resetForm(); }); - } - if (options.clearForm) { - callbacks.push(function() { $form.clearForm(); }); - } - - // perform a load on the target only if dataType is not provided - if (!options.dataType && options.target) { - var oldSuccess = options.success || function(){}; - callbacks.push(function(data) { - var fn = options.replaceTarget ? 'replaceWith' : 'html'; - $(options.target)[fn](data).each(oldSuccess, arguments); - }); - } - else if (options.success) { - callbacks.push(options.success); - } - - options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg - var context = options.context || options; // jQuery 1.4+ supports scope context - for (var i=0, max=callbacks.length; i < max; i++) { - callbacks[i].apply(context, [data, status, xhr || $form, $form]); - } - }; - - // are there files to upload? - var fileInputs = $('input:file', this).length > 0; - var mp = 'multipart/form-data'; - var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); - - // options.iframe allows user to force iframe mode - // 06-NOV-09: now defaulting to iframe mode if file input is detected - if (options.iframe !== false && (fileInputs || options.iframe || multipart)) { - // hack to fix Safari hang (thanks to Tim Molendijk for this) - // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d - if (options.closeKeepAlive) { - $.get(options.closeKeepAlive, fileUpload); - } - else { - fileUpload(); - } - } - else { - $.ajax(options); - } - - // fire 'notify' event - this.trigger('form-submit-notify', [this, options]); - return this; - - - // private function for handling file uploads (hat tip to YAHOO!) - function fileUpload() { - var form = $form[0]; - - if ($(':input[name=submit],:input[id=submit]', form).length) { - // if there is an input with a name or id of 'submit' then we won't be - // able to invoke the submit fn on the form (at least not x-browser) - alert('Error: Form elements must not have name or id of "submit".'); - return; - } - - var s = $.extend(true, {}, $.ajaxSettings, options); - s.context = s.context || s; - var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id; - var $io = $('