X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=www%2Fplugins-dist%2Furls_etendues%2Furls%2Farbo.php;fp=www%2Fplugins-dist%2Furls_etendues%2Furls%2Farbo.php;h=b985c22af4ba406eb2d4453e0e8e21a24561a6e9;hb=4f443dce95ff6f8221c189880a70c74ce1c1f238;hp=77bd2ef14403569edaf3cb7dbb59004f8edfdf7d;hpb=4a628e9b277d3617535f99d663ca79fa2e891177;p=lhc%2Fweb%2Fwww.git diff --git a/www/plugins-dist/urls_etendues/urls/arbo.php b/www/plugins-dist/urls_etendues/urls/arbo.php index 77bd2ef1..b985c22a 100644 --- a/www/plugins-dist/urls_etendues/urls/arbo.php +++ b/www/plugins-dist/urls_etendues/urls/arbo.php @@ -10,7 +10,9 @@ * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * \***************************************************************************/ -if (!defined("_ECRIRE_INC_VERSION")) return; // securiser +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} // securiser # donner un exemple d'url pour le formulaire de choix define('URLS_ARBO_EXEMPLE', '/article/titre'); @@ -28,67 +30,103 @@ defined('CONFIRMER_MODIFIER_URL') || define('CONFIRMER_MODIFIER_URL', false); * que vous pourriez avoir mis dans ce fichier) ; si votre site est en * "sous-repertoire", vous devrez aussi editer la ligne "RewriteBase" ce fichier. * Les URLs definies seront alors redirigees vers les fichiers de SPIP. - * + * * Choisissez "arbo" dans les pages de configuration d'URL * * SPIP calculera alors ses liens sous la forme "Mon-titre-d-article". * Variantes : - * + * * Terminaison : * les terminaisons ne *sont pas* stockees en base, elles servent juste * a rendre les url jolies ou conformes a un usage * pour avoir des url terminant par html * define ('_terminaison_urls_arbo', '.html'); - * + * * pour preciser des terminaisons particulieres pour certains types * $GLOBALS['url_arbo_terminaisons']=array( * 'rubrique' => '/', * 'mot' => '', * 'groupe' => '/', * 'defaut' => '.html'); - * + * * pour avoir des url numeriques (id) du type 12/5/4/article/23 * define ('_URLS_ARBO_MIN',255); - * - * + * + * * pour conserver la casse des titres dans les url * define ('_url_arbo_minuscules',0); - * - * pour choisir le caractere de separation titre-id en cas de doublon + * + * pour choisir le caractere de separation titre-id en cas de doublon * (ne pas utiliser '/') * define ('_url_arbo_sep_id','-'); - * + * * pour modifier la hierarchie apparente dans la constitution des urls * ex pour que les mots soient classes par groupes * $GLOBALS['url_arbo_parents']=array( - * 'article'=>array('id_rubrique','rubrique'), - * 'rubrique'=>array('id_parent','rubrique'), - * 'breve'=>array('id_rubrique','rubrique'), - * 'site'=>array('id_rubrique','rubrique'), - * 'mot'=>array('id_groupe','groupes_mot')); - * + * 'article'=>array('id_rubrique','rubrique'), + * 'rubrique'=>array('id_parent','rubrique'), + * 'breve'=>array('id_rubrique','rubrique'), + * 'site'=>array('id_rubrique','rubrique'), + * 'mot'=>array('id_groupe','groupes_mot')); + * * pour personaliser les types * $GLOBALS['url_arbo_types']=array( * 'rubrique'=>'', // pas de type pour les rubriques * 'article'=>'a', * 'mot'=>'tags' * ); - * + * */ +include_spip('inc/xcache'); +if (!function_exists('Cache')) { + function Cache() { + return null; + } +} -$config_urls_arbo = isset($GLOBALS['meta']['urls_arbo'])?unserialize($GLOBALS['meta']['urls_arbo']):array(); -if (!defined('_debut_urls_arbo')) define('_debut_urls_arbo', ''); -if (!defined('_terminaison_urls_arbo')) define('_terminaison_urls_arbo', ''); +$config_urls_arbo = isset($GLOBALS['meta']['urls_arbo']) ? unserialize($GLOBALS['meta']['urls_arbo']) : array(); +if (!defined('_debut_urls_arbo')) { + define('_debut_urls_arbo', ''); +} +if (!defined('_terminaison_urls_arbo')) { + define('_terminaison_urls_arbo', ''); +} // pour choisir le caractere de separation titre-id en cas de doublon // (ne pas utiliser '/') -if (!defined('_url_arbo_sep_id')) define('_url_arbo_sep_id',isset($config_urls_arbo['url_arbo_sep_id'])?$config_urls_arbo['url_arbo_sep_id']:'-'); +if (!defined('_url_arbo_sep_id')) { + define('_url_arbo_sep_id', isset($config_urls_arbo['url_arbo_sep_id']) ? $config_urls_arbo['url_arbo_sep_id'] : '-'); +} // option pour tout passer en minuscules -if (!defined('_url_arbo_minuscules')) define('_url_arbo_minuscules',isset($config_urls_arbo['url_arbo_minuscules'])?$config_urls_arbo['url_arbo_minuscules']:1); -if (!defined('_URLS_ARBO_MAX')) define('_URLS_ARBO_MAX', isset($config_urls_arbo['URLS_ARBO_MAX'])?$config_urls_arbo['URLS_ARBO_MAX']:80); -if (!defined('_URLS_ARBO_MIN')) define('_URLS_ARBO_MIN', isset($config_urls_arbo['URLS_ARBO_MIN'])?$config_urls_arbo['URLS_ARBO_MIN']:3); +if (!defined('_url_arbo_minuscules')) { + define('_url_arbo_minuscules', isset($config_urls_arbo['url_arbo_minuscules']) ? $config_urls_arbo['url_arbo_minuscules'] : 1); +} +if (!defined('_URLS_ARBO_MAX')) { + define('_URLS_ARBO_MAX', isset($config_urls_arbo['URLS_ARBO_MAX']) ? $config_urls_arbo['URLS_ARBO_MAX'] : 80); +} +if (!defined('_URLS_ARBO_MIN')) { + define('_URLS_ARBO_MIN', isset($config_urls_arbo['URLS_ARBO_MIN']) ? $config_urls_arbo['URLS_ARBO_MIN'] : 3); +} + +if (!defined('_url_sep_id')) { + define('_url_sep_id', _url_arbo_sep_id); +} + +// peut prendre plusieurs valeurs : +// - false pour ne pas gerer le multilinguisme => fonctionnement historique +// define('_url_arbo_multilang',false); +// - la valeur d'une langue pour forcer le calcul des URLs dans une langue donnee +// define('_url_arbo_multilang','en'); +// - true pour forcer la gestion complete du multilinguisme : +// calcul des URLs dans toutes les langues possibles, +// ajout d'un premier segment fr/ dans les URLs pour definir la langue +// prise en compte de l'argument lang=xx dans $args au moment de generer l'URL +// define('_url_arbo_multilang',true); + +if (!defined('_url_arbo_multilang')) { + define('_url_arbo_multilang',false); +} -if (!defined('_url_sep_id')) define('_url_sep_id',_url_arbo_sep_id); // Ces chaines servaient de marqueurs a l'epoque ou les URL propres devaient // indiquer la table ou les chercher (articles, auteurs etc), @@ -97,7 +135,9 @@ if (!defined('_url_sep_id')) define('_url_sep_id',_url_arbo_sep_id); // mais les preg_match restent necessaires pour gerer les anciens signets. #define('_MARQUEUR_URL', serialize(array('rubrique1' => '-', 'rubrique2' => '-', 'breve1' => '+', 'breve2' => '+', 'site1' => '@', 'site2' => '@', 'auteur1' => '_', 'auteur2' => '_', 'mot1' => '+-', 'mot2' => '-+'))); -if (!defined('_MARQUEUR_URL')) define('_MARQUEUR_URL', false); +if (!defined('_MARQUEUR_URL')) { + define('_MARQUEUR_URL', false); +} /** * Definir les parentees utilisees pour construire des urls arborescentes @@ -105,19 +145,21 @@ if (!defined('_MARQUEUR_URL')) define('_MARQUEUR_URL', false); * @param string $type * @return string */ -function url_arbo_parent($type){ +function url_arbo_parent($type) { static $parents = null; - if (is_null($parents)){ + if (is_null($parents)) { $parents = array( - 'article'=>array('id_rubrique','rubrique'), - 'rubrique'=>array('id_parent','rubrique'), - 'breve'=>array('id_rubrique','rubrique'), - 'site'=>array('id_rubrique','rubrique')); - if (isset($GLOBALS['url_arbo_parents']) AND !isset($_REQUEST['url_arbo_parents'])){ - $parents = array_merge($parents,$GLOBALS['url_arbo_parents']); - } - } - return (isset($parents[$type])?$parents[$type]:''); + 'article' => array('id_rubrique', 'rubrique'), + 'rubrique' => array('id_parent', 'rubrique'), + 'breve' => array('id_rubrique', 'rubrique'), + 'site' => array('id_rubrique', 'rubrique') + ); + if (isset($GLOBALS['url_arbo_parents']) and !isset($_REQUEST['url_arbo_parents'])) { + $parents = array_merge($parents, $GLOBALS['url_arbo_parents']); + } + } + + return (isset($parents[$type]) ? $parents[$type] : ''); } /** @@ -128,21 +170,29 @@ function url_arbo_parent($type){ * @param string $type * @return string */ -function url_arbo_terminaison($type){ +function url_arbo_terminaison($type) { static $terminaison_types = null; - if ($terminaison_types==null){ - $terminaison_types = array('rubrique' => '/','mot' => '','defaut' => defined('_terminaison_urls_arbo')?_terminaison_urls_arbo:'.html'); - if (isset($GLOBALS['url_arbo_terminaisons'])) - $terminaison_types = array_merge($terminaison_types,$GLOBALS['url_arbo_terminaisons']); + if ($terminaison_types == null) { + $terminaison_types = array( + 'rubrique' => '/', + 'mot' => '', + 'defaut' => defined('_terminaison_urls_arbo') ? _terminaison_urls_arbo : '.html' + ); + if (isset($GLOBALS['url_arbo_terminaisons'])) { + $terminaison_types = array_merge($terminaison_types, $GLOBALS['url_arbo_terminaisons']); + } } // si c'est un appel avec type='' c'est pour avoir la liste des terminaisons - if (!$type) + if (!$type) { return array_unique(array_values($terminaison_types)); - if (isset($terminaison_types[$type])) + } + if (isset($terminaison_types[$type])) { return $terminaison_types[$type]; - elseif (isset($terminaison_types['defaut'])) + } elseif (isset($terminaison_types['defaut'])) { return $terminaison_types['defaut']; - return ""; + } + + return ''; } /** @@ -153,19 +203,22 @@ function url_arbo_terminaison($type){ * @param string $type * @return array|string */ -function url_arbo_type($type){ +function url_arbo_type($type) { static $synonymes_types = null; - if (!$synonymes_types){ - $synonymes_types = array('rubrique'=>''); - if (isset($GLOBALS['url_arbo_types']) AND is_array($GLOBALS['url_arbo_types'])) - $synonymes_types = array_merge($synonymes_types,$GLOBALS['url_arbo_types']); + if (!$synonymes_types) { + $synonymes_types = array('rubrique' => ''); + if (isset($GLOBALS['url_arbo_types']) and is_array($GLOBALS['url_arbo_types'])) { + $synonymes_types = array_merge($synonymes_types, $GLOBALS['url_arbo_types']); + } } // si c'est un appel avec type='' c'est pour avoir la liste inversee des synonymes - if (!$type) + if (!$type) { return array_flip($synonymes_types); - return - ($t=(isset($synonymes_types[$type])?$synonymes_types[$type]:$type)) // le type ou son synonyme - . ($t?'/':''); // le / eventuel pour separer, si le synonyme n'est pas vide + } + + return + ($t = (isset($synonymes_types[$type]) ? $synonymes_types[$type] : $type)) // le type ou son synonyme + . ($t ? '/' : ''); // le / eventuel pour separer, si le synonyme n'est pas vide } /** @@ -180,18 +233,29 @@ function url_arbo_type($type){ */ function urls_arbo_creer_chaine_url($x) { // NB: ici url_old ne sert pas, mais un plugin qui ajouterait une date - // pourrait l'utiliser pour juste ajouter la + // pourrait l'utiliser pour juste ajouter la $url_old = $x['data']; $objet = $x['objet']; include_spip('inc/filtres'); include_spip('action/editer_url'); - if (!$url = url_nettoyer($objet['titre'],_URLS_ARBO_MAX,_URLS_ARBO_MIN,'-',_url_arbo_minuscules?'strtolower':'')) + if (!$url = url_nettoyer( + $objet['titre'], + _URLS_ARBO_MAX, + _URLS_ARBO_MIN, + '-', + _url_arbo_minuscules ? 'spip_strtolower' : '' + )) { $url = $objet['id_objet']; - - $x['data'] = - url_arbo_type($objet['type']) // le type ou son synonyme - . $url; // le titre + } + + // le type ou son synonyme + $prefixe = url_arbo_type($objet['type']); + if (strpos($prefixe, '<') !== false) { + $prefixe = extraire_multi($prefixe); + $prefixe = textebrut($prefixe); + } + $x['data'] = $prefixe . $url; // le titre return $x; } @@ -204,60 +268,92 @@ function urls_arbo_creer_chaine_url($x) { * @param string $type * @param string $parent * @param string $type_parent + * @param array $contexte * @return string */ -function declarer_url_arbo_rec($url,$type,$parent,$type_parent){ - if (is_null($parent)){ +function declarer_url_arbo_rec($url, $type, $parent, $type_parent, $contexte = array()) { + if (is_null($parent)) { return $url; } - // Si pas de parent ou si son URL est vide, on ne renvoit que l'URL de l'objet en court - if ($parent==0 or !($url_parent = declarer_url_arbo($type_parent?$type_parent:'rubrique',$parent))){ - return rtrim($url,'/'); + // le contexte parent ne se transmet pas + if (isset($contexte['id_parent'])) { + unset($contexte['id_parent']); } - // Sinon on renvoit l'URL de l'objet concaténée avec celle du parent + // Si pas de parent ou si son URL est vide, on ne renvoit que l'URL de l'objet en court + if ($parent == 0 or !($url_parent = declarer_url_arbo($type_parent ? $type_parent : 'rubrique', $parent, $contexte))) { + return rtrim($url, '/'); + } // Sinon on renvoit l'URL de l'objet concaténée avec celle du parent else { - return rtrim($url_parent,'/') . '/' . rtrim($url,'/'); + return rtrim($url_parent, '/') . '/' . rtrim($url, '/'); } } /** * Renseigner les infos les plus recentes de l'url d'un objet * et de quoi la (re)construire si besoin + * * @param string $type * @param int $id_objet + * @param array $contexte + * id_parent : rubrique parent * @return bool|null|array */ -function renseigner_url_arbo($type,$id_objet){ +function renseigner_url_arbo($type, $id_objet, $contexte = array()) { $urls = array(); $trouver_table = charger_fonction('trouver_table', 'base'); $desc = $trouver_table(table_objet($type)); $table = $desc['table']; - $col_id = @$desc['key']["PRIMARY KEY"]; - if (!$col_id) return false; // Quand $type ne reference pas une table + $col_id = @$desc['key']['PRIMARY KEY']; + if (!$col_id) { + return false; + } // Quand $type ne reference pas une table $id_objet = intval($id_objet); + $id_parent = (isset($contexte['id_parent'])?$contexte['id_parent']:null); + $langue = (isset($contexte['langue'])?$contexte['langue']:''); + $champ_titre = $desc['titre'] ? $desc['titre'] : 'titre'; - + // parent $champ_parent = url_arbo_parent($type); $sel_parent = ', 0 as parent'; - $order_by_parent = ""; - if ($champ_parent){ - $sel_parent = ", O.".reset($champ_parent).' as parent'; - // trouver l'url qui matche le parent en premier - $order_by_parent = "O.".reset($champ_parent)."=U.id_parent DESC, "; + $order_by_parent = ''; + if ($champ_parent) { + // si un parent est fourni est qu'il est legitime, on recherche une URL pour ce parent + if ($id_parent + and $type_parent = end($champ_parent) + and $url_verifier_parent_objet = charger_fonction('url_verifier_parent_objet', 'inc', true) + and $url_verifier_parent_objet($type, $id_objet, $type_parent, $id_parent)) { + $sel_parent = ', '.intval($id_parent) . ' as parent'; + // trouver l'url qui matche le parent en premier + $order_by_parent = 'U.id_parent='.intval($id_parent).' DESC, '; + } else { + // sinon on prend son parent direct fourni par $champ_parent + $sel_parent = ', O.' . reset($champ_parent) . ' as parent'; + // trouver l'url qui matche le parent en premier + $order_by_parent = 'O.' . reset($champ_parent) . '=U.id_parent DESC, '; + } + } + $order_by_langue = "U.langue='' DESC, "; + if ($langue) { + $order_by_langue = 'U.langue='.sql_quote($langue).' DESC, ' . $order_by_langue; } + // Recuperer une URL propre correspondant a l'objet. - $row = sql_fetsel("U.url, U.date, U.id_parent, U.perma, $champ_titre $sel_parent", - "$table AS O LEFT JOIN spip_urls AS U ON (U.type='$type' AND U.id_objet=O.$col_id)", - "O.$col_id=$id_objet", - '', - $order_by_parent.'U.perma DESC, U.date DESC', 1); - if ($row){ + $row = sql_fetsel( + "U.url, U.date, U.id_parent, U.perma, U.langue, $champ_titre $sel_parent", + "$table AS O LEFT JOIN spip_urls AS U ON (U.type='$type' AND U.id_objet=O.$col_id)", + "O.$col_id=$id_objet", + '', + $order_by_parent . 'U.perma DESC, ' . $order_by_langue . 'U.date DESC', + 1 + ); + if ($row) { $urls[$type][$id_objet] = $row; - $urls[$type][$id_objet]['type_parent'] = $champ_parent?end($champ_parent):''; + $urls[$type][$id_objet]['type_parent'] = $champ_parent ? end($champ_parent) : ''; } - return isset($urls[$type][$id_objet])?$urls[$type][$id_objet]:null; + + return isset($urls[$type][$id_objet]) ? $urls[$type][$id_objet] : null; } /** @@ -267,10 +363,29 @@ function renseigner_url_arbo($type,$id_objet){ * * @param string $type * @param int $id_objet + * @param array $contexte + * id_parent : rubrique parent + * langue : langue courante pour laquelle on veut l'URL * @return string */ -function declarer_url_arbo($type, $id_objet) { - static $urls=array(); +function declarer_url_arbo($type, $id_objet, $contexte = array()) { + static $urls = array(); + // utiliser un cache memoire pour aller plus vite + if (!is_null($C = Cache())) { + return $C; + } + // contexte de langue si pas defini, en fonction de la configuration + if (!isset($contexte['langue'])) { + if (!_url_arbo_multilang) { + $contexte['langue'] = ''; + } elseif (_url_arbo_multilang === true) { + $contexte['langue'] = $GLOBALS['spip_lang']; + } else { + $contexte['langue'] = _url_arbo_multilang; + } + } + ksort($contexte); + $hash = json_encode($contexte); // Se contenter de cette URL si elle existe ; // sauf si on invoque par "voir en ligne" avec droit de modifier l'url @@ -278,58 +393,100 @@ function declarer_url_arbo($type, $id_objet) { // l'autorisation est verifiee apres avoir calcule la nouvelle url propre // car si elle ne change pas, cela ne sert a rien de verifier les autorisations // qui requetent en base - $modifier_url = (defined('_VAR_URLS') AND _VAR_URLS); - - if (!isset($urls[$type][$id_objet]) OR $modifier_url) { - $r = renseigner_url_arbo($type,$id_objet); + $modifier_url = (defined('_VAR_URLS') and _VAR_URLS); + + if (!isset($urls[$type][$id_objet][$hash]) or $modifier_url) { + $r = renseigner_url_arbo($type, $id_objet, $contexte); // Quand $type ne reference pas une table - if ($r===false) + if ($r === false) { return false; + } - if (!is_null($r)) - $urls[$type][$id_objet] = $r; + if (!is_null($r)) { + $urls[$type][$id_objet][$hash] = $r; + } } - if (!isset($urls[$type][$id_objet])) return ""; # objet inexistant + if (!isset($urls[$type][$id_objet][$hash])) { + return ''; + } # objet inexistant - $url_propre = $urls[$type][$id_objet]['url']; + $u = &$urls[$type][$id_objet][$hash]; + $url_propre = $u['url']; // si on a trouve l'url // et que le parent est bon // et (permanente ou pas de demande de modif) if (!is_null($url_propre) - AND $urls[$type][$id_objet]['id_parent'] == $urls[$type][$id_objet]['parent'] - AND ($urls[$type][$id_objet]['perma'] OR !$modifier_url)) - return declarer_url_arbo_rec($url_propre,$type, - isset($urls[$type][$id_objet]['parent'])?$urls[$type][$id_objet]['parent']:0, - isset($urls[$type][$id_objet]['type_parent'])?$urls[$type][$id_objet]['type_parent']:null); + and $u['id_parent'] == $u['parent'] + and ($u['perma'] or !$modifier_url) + ) { + return declarer_url_arbo_rec( + $url_propre, + $type, + isset($u['parent']) ? $u['parent'] : 0, + isset($u['type_parent']) ? $u['type_parent'] : null, + $contexte + ); + } // Si URL inconnue ou maj forcee sur une url non permanente, recreer une url $url = $url_propre; - if (is_null($url_propre) OR ($modifier_url AND !$urls[$type][$id_objet]['perma'])) { - $url = pipeline('arbo_creer_chaine_url', - array( - 'data' => $url_propre, // le vieux url_propre - 'objet' => array_merge($urls[$type][$id_objet], - array('type' => $type, 'id_objet' => $id_objet) - ) - ) - ); + $urls_langues = array(); + if (is_null($url_propre) or ($modifier_url and !$u['perma'])) { + $langues = array(); + if (_url_arbo_multilang === true) { + include_spip('inc/lang'); + $langues = (isset($GLOBALS['meta']['langues_multilingue']) ? $GLOBALS['meta']['langues_multilingue'] : ''); + $langues = explode(',', $langues); + if ($k = array_search(_LANGUE_PAR_DEFAUT, $langues)) { + unset($langues[$k]); + array_unshift($langues, _LANGUE_PAR_DEFAUT); + } + } + if (!in_array($contexte['langue'], $langues)) { + $langues[] = $contexte['langue']; + } + + // on calcule l'URL de chaque langue utile (langue courante, langue forcee ou toutes les langues utilises) + $langue_courante = $GLOBALS['spip_lang']; - // Eviter de tamponner les URLs a l'ancienne (cas d'un article - // intitule "auteur2") include_spip('inc/urls'); $objets = urls_liste_objets(); - if (preg_match(',^('.$objets.')[0-9]*$,', $url, $r) - AND $r[1] != $type) - $url = $url._url_arbo_sep_id.$id_objet; + + foreach ($langues as $l) { + if ($l) { + changer_langue($l); + } + $urls_langues[$l] = pipeline( + 'arbo_creer_chaine_url', + array( + 'data' => $url_propre, // le vieux url_propre + 'objet' => array_merge($u, array('type' => $type, 'id_objet' => $id_objet)) + ) + ); + + // Eviter de tamponner les URLs a l'ancienne (cas d'un article + // intitule "auteur2") + if (preg_match(',^(' . $objets . ')[0-9]*$,', $urls_langues[$l], $r) + and $r[1] != $type + ) { + $urls_langues[$l] = $urls_langues[$l] . _url_arbo_sep_id . $id_objet; + } + } + // retablir la $langue_courante par securite, au cas ou on a change de langue + changer_langue($langue_courante); + + $url = $urls_langues[$contexte['langue']]; } // Pas de changement d'url ni de parent if ($url == $url_propre - AND $urls[$type][$id_objet]['id_parent'] == $urls[$type][$id_objet]['parent']) - return declarer_url_arbo_rec($url_propre,$type,$urls[$type][$id_objet]['parent'],$urls[$type][$id_objet]['type_parent']); + and $u['id_parent'] == $u['parent'] + ) { + return declarer_url_arbo_rec($url_propre, $type, $u['parent'], $u['type_parent'], $contexte); + } // verifier l'autorisation, maintenant qu'on est sur qu'on va agir if ($modifier_url) { @@ -338,31 +495,45 @@ function declarer_url_arbo($type, $id_objet) { } // Verifier si l'utilisateur veut effectivement changer l'URL if ($modifier_url - AND CONFIRMER_MODIFIER_URL - AND $url_propre + and CONFIRMER_MODIFIER_URL + and $url_propre // on essaye pas de regenerer une url en -xxx (suffixe id anti collision) - AND $url != preg_replace('/'.preg_quote(_url_propres_sep_id,'/').'.*/', '', $url_propre)) + and $url != preg_replace('/' . preg_quote(_url_propres_sep_id, '/') . '.*/', '', $url_propre) + ) { $confirmer = true; - else + } else { $confirmer = false; + } - if ($confirmer AND !_request('ok')) { - die ("vous changez d'url ? $url_propre -> $url"); + if ($confirmer and !_request('ok')) { + die("vous changez d'url ? $url_propre -> $url"); } - $set = array('url' => $url, 'type' => $type, 'id_objet' => $id_objet, 'id_parent'=>$urls[$type][$id_objet]['parent'],'perma'=>intval($urls[$type][$id_objet]['perma'])); + // on enregistre toutes les langues include_spip('action/editer_url'); - if (url_insert($set,$confirmer,_url_arbo_sep_id)){ - $urls[$type][$id_objet]['url'] = $set['url']; - $urls[$type][$id_objet]['id_parent'] = $set['id_parent']; - } - else { - // l'insertion a echoue, - //serveur out ? retourner au mieux - $urls[$type][$id_objet]['url']=$url_propre; + foreach ($urls_langues as $langue => $url) { + $set = array( + 'url' => $url, + 'type' => $type, + 'id_objet' => $id_objet, + 'id_parent' => $u['parent'], + 'langue' => $langue, + 'perma' => intval($u['perma']) + ); + $res = url_insert($set, $confirmer, _url_arbo_sep_id); + if ($langue == $contexte['langue']) { + if ($res) { + $u['url'] = $set['url']; + $u['id_parent'] = $set['id_parent']; + } else { + // l'insertion a echoue, + //serveur out ? retourner au mieux + $u['url'] = $url_propre; + } + } } - return declarer_url_arbo_rec($urls[$type][$id_objet]['url'],$type,$urls[$type][$id_objet]['parent'],$urls[$type][$id_objet]['type_parent']); + return declarer_url_arbo_rec($u['url'], $type, $u['parent'], $u['type_parent'], $contexte); } /** @@ -376,37 +547,78 @@ function declarer_url_arbo($type, $id_objet) { * @param string $ancre * @return string */ -function _generer_url_arbo($type, $id, $args='', $ancre='') { - - if ($generer_url_externe = charger_fonction("generer_url_$type",'urls',true)) { +function _generer_url_arbo($type, $id, $args = '', $ancre = '') { + if ($generer_url_externe = charger_fonction("generer_url_$type", 'urls', true)) { $url = $generer_url_externe($id, $args, $ancre); - if (NULL != $url) return $url; + if (null != $url) { + return $url; + } } + $debut_langue = ''; + // Mode propre - $propre = declarer_url_arbo($type, $id); + $c = array(); + + parse_str($args, $contexte); + // choisir le contexte de langue en fonction de la configuration + $c['langue'] = ''; + if (_url_arbo_multilang === true) { + if (isset($contexte['lang']) and $contexte['lang']) { + $c['langue'] = $contexte['lang']; + $debut_langue = $c['langue'] .'/'; + unset($contexte['lang']); + $args = http_build_query($contexte); + } elseif (isset($GLOBALS['spip_lang']) and $GLOBALS['spip_lang']) { + $c['langue'] = $GLOBALS['spip_lang']; + $debut_langue = $c['langue'] .'/'; + } + } elseif (_url_arbo_multilang) { + $c['langue'] = _url_arbo_multilang; + } + $propre = declarer_url_arbo($type, $id, $c); - if ($propre === false) return ''; // objet inconnu. raccourci ? + // si le parent est fourni en contexte dans le $args, verifier si l'URL relative a ce parent est la meme ou non + $champ_parent = url_arbo_parent($type); + if ($champ_parent + and $champ_parent = reset($champ_parent) + and isset($contexte[$champ_parent]) and $contexte[$champ_parent]) { + $c['id_parent'] = $contexte[$champ_parent]; + $propre_contexte = declarer_url_arbo($type, $id, $c); + // si l'URL est differente on la prend et on enleve l'argument de l'URL (redondance puisque parent defini par l'URL elle meme) + if ($propre_contexte !== $propre) { + $propre = $propre_contexte; + unset($contexte[$champ_parent]); + $args = http_build_query($contexte); + } + } + + + if ($propre === false) { + return ''; + } // objet inconnu. raccourci ? if ($propre) { $url = _debut_urls_arbo - . rtrim($propre,'/') + . $debut_langue + . rtrim($propre, '/') . url_arbo_terminaison($type); } else { - // objet connu mais sans possibilite d'URL lisible, revenir au defaut include_spip('base/connect_sql'); $id_type = id_table_objet($type); - $url = get_spip_script('./')."?"._SPIP_PAGE."=$type&$id_type=$id"; + $url = get_spip_script('./') . '?' . _SPIP_PAGE . "=$type&$id_type=$id"; } // Ajouter les args - if ($args) - $url .= ((strpos($url, '?')===false) ? '?' : '&') . $args; + if ($args) { + $url .= ((strpos($url, '?') === false) ? '?' : '&') . $args; + } // Ajouter l'ancre - if ($ancre) + if ($ancre) { $url .= "#$ancre"; + } return _DIR_RACINE . $url; } @@ -425,20 +637,23 @@ function _generer_url_arbo($type, $id, $args='', $ancre='') { * @param string $ancre * @return array|string */ -function urls_arbo_dist($i, $entite, $args='', $ancre='') { - if (is_numeric($i)) +function urls_arbo_dist($i, $entite, $args = '', $ancre = '') { + if (is_numeric($i)) { return _generer_url_arbo($entite, $i, $args, $ancre); + } // traiter les injections du type domaine.org/spip.php/cestnimportequoi/ou/encore/plus/rubrique23 - if ($GLOBALS['profondeur_url']>0 AND $entite=='sommaire'){ + if ($GLOBALS['profondeur_url'] > 0 and $entite == 'sommaire') { $entite = 'type_urls'; } // recuperer les &debut_xx; - if (is_array($args)) + if (is_array($args)) { $contexte = $args; - else - parse_str($args,$contexte); + $args = http_build_query($contexte); + } else { + parse_str($args, $contexte); + } $url = $i; $id_objet = $type = 0; @@ -446,24 +661,31 @@ function urls_arbo_dist($i, $entite, $args='', $ancre='') { // Migration depuis anciennes URLs ? // traiter les injections domain.tld/spip.php/n/importe/quoi/rubrique23 - if ($GLOBALS['profondeur_url']<=0 - AND $_SERVER['REQUEST_METHOD'] != 'POST') { + if ($GLOBALS['profondeur_url'] <= 0 + and $_SERVER['REQUEST_METHOD'] != 'POST' + ) { include_spip('inc/urls'); $r = nettoyer_url_page($i, $contexte); if ($r) { - list($contexte, $type,,, $suite) = $r; + list($contexte, $type, , , $suite) = $r; $_id = id_table_objet($type); $id_objet = $contexte[$_id]; $url_propre = generer_url_entite($id_objet, $type); if (strlen($url_propre) - AND !strstr($url,$url_propre)) { - list(,$hash) = explode('#', $url_propre); + and !strstr($url, $url_propre) + and ( + objet_test_si_publie($type, $id_objet) + OR (defined('_VAR_PREVIEW') and _VAR_PREVIEW and autoriser('voir', $type, $id_objet)) + ) + ) { + list(, $hash) = array_pad(explode('#', $url_propre), 2, null); $args = array(); - foreach(array_filter(explode('&', $suite)) as $fragment) { - if ($fragment != "$_id=$id_objet") + foreach (array_filter(explode('&', $suite)) as $fragment) { + if ($fragment != "$_id=$id_objet") { $args[] = $fragment; + } } - $url_redirect = generer_url_entite($id_objet, $type, join('&',array_filter($args)), $hash); + $url_redirect = generer_url_entite($id_objet, $type, join('&', array_filter($args)), $hash); return array($contexte, $type, $url_redirect, $type); } @@ -472,29 +694,21 @@ function urls_arbo_dist($i, $entite, $args='', $ancre='') { /* Fin compatibilite anciennes urls */ // Chercher les valeurs d'environnement qui indiquent l'url-propre - if (isset($_SERVER['REDIRECT_url_propre'])) - $url_propre = $_SERVER['REDIRECT_url_propre']; - elseif (isset($_ENV['url_propre'])) - $url_propre = $_ENV['url_propre']; - else { - // ne prendre que le segment d'url qui correspond, en fonction de la profondeur calculee - $url = ltrim($url,'/'); - $url = explode('/',$url); - while (count($url)>$GLOBALS['profondeur_url']+1) - array_shift($url); - $url = implode('/',$url); - $url_propre = preg_replace(',[?].*,', '', $url); - } + $url_propre = preg_replace(',[?].*,', '', $url); // Mode Query-String ? if (!$url_propre - AND preg_match(',[?]([^=/?&]+)(&.*)?$,', $url, $r)) { + and preg_match(',[?]([^=/?&]+)(&.*)?$,', $url, $r) + ) { $url_propre = $r[1]; } if (!$url_propre - OR $url_propre==_DIR_RESTREINT_ABS - OR $url_propre==_SPIP_SCRIPT) return; // qu'est-ce qu'il veut ??? + or $url_propre == _DIR_RESTREINT_ABS + or $url_propre == _SPIP_SCRIPT + ) { + return; + } // qu'est-ce qu'il veut ??? include_spip('base/abstract_sql'); // chercher dans la table des URLS @@ -503,70 +717,101 @@ function urls_arbo_dist($i, $entite, $args='', $ancre='') { $url_propre = rawurldecode($url_propre); // Compatibilite avec .htm/.html et autres terminaisons - $t = array_diff(array_unique(array_merge(array('.html','.htm','/'),url_arbo_terminaison(''))),array('')); - if (count($t)) + $t = array_diff(array_unique(array_merge(array('.html', '.htm', '/'), url_arbo_terminaison(''))), array('')); + if (count($t)) { $url_propre = preg_replace('{(' - .implode('|',array_map('preg_quote',$t)).')$}i', '', $url_propre); + . implode('|', array_map('preg_quote', $t)) . ')$}i', '', $url_propre); + } - if (strlen($url_propre) AND !preg_match(',^[^/]*[.]php,',$url_propre)){ + if (strlen($url_propre) and !preg_match(',^[^/]*[.]php,', $url_propre)) { $parents_vus = array(); - + // recuperer tous les objets de larbo xxx/article/yyy/mot/zzzz // on parcourt les segments de gauche a droite // pour pouvoir contextualiser un segment par son parent - $url_arbo = explode('/',$url_propre); + $url_arbo = explode('/', $url_propre); $url_arbo_new = array(); $dernier_parent_vu = false; $objet_segments = 0; - while (count($url_arbo)>0){ - $type=null; - if (count($url_arbo)>1) + + $langue = ''; + if (_url_arbo_multilang === true) { + // la langue : si fourni en QS prioritaire car vient du skel ou de forcer_lang + if (isset($contexte['lang'])) { + $langue = $contexte['lang']; + } + // le premier segment peut etre la langue : l'extraire + // on le prend en compte si lang non fournie par la QS sinon on l'ignore + include_spip('action/editer_url'); // pour url_verifier_langue + if (count($url_arbo) > 1 + and $first = reset($url_arbo) + and url_verifier_langue($first)) { + array_shift($url_arbo); + if (!$langue) { + $contexte['lang'] = $langue = $first; + } + } + } elseif (_url_arbo_multilang) { + $langue = _url_arbo_multilang; + } + + while (count($url_arbo) > 0) { + $type = null; + if (count($url_arbo) > 1) { $type = array_shift($url_arbo); + } $url_segment = array_shift($url_arbo); // Rechercher le segment de candidat // si on est dans un contexte de parent, donne par le segment precedent, // prefixer le segment recherche avec ce contexte - $cp = "0"; // par defaut : parent racine, id=0 - if ($dernier_parent_vu) + $cp = '0'; // par defaut : parent racine, id=0 + if ($dernier_parent_vu) { $cp = $parents_vus[$dernier_parent_vu]; + } // d'abord recherche avec prefixe parent, en une requete car aucun risque de colision - $row=sql_fetsel('id_objet, type, url', - 'spip_urls', - is_null($type) - ? "url=".sql_quote($url_segment, '', 'TEXT') - : sql_in('url',array("$type/$url_segment",$type)), - '', - // en priorite celui qui a le bon parent et les deux segments - // puis le bon parent avec 1 segment - // puis un parent indefini (le 0 de preference) et les deux segments - // puis un parent indefini (le 0 de preference) et 1 segment - (intval($cp)?"id_parent=".intval($cp)." DESC, ":"id_parent>=0 DESC, ")."segments DESC, id_parent" + $row = sql_fetsel( + 'id_objet, type, url', + 'spip_urls', + is_null($type) + ? 'url=' . sql_quote($url_segment, '', 'TEXT') + : sql_in('url', array("$type/$url_segment", $type)), + '', + // en priorite celui qui a le bon parent + // puis la bonne langue puis la langue '' + // puis les deux segments puis 1 seul segment + // + // si parent indefini on privilegie id_parent=0 avec la derniere clause du order + (intval($cp) ? 'id_parent=' . intval($cp) . ' DESC, ' : 'id_parent>=0 DESC, ') + . ($langue?'langue='.sql_quote($langue).' DESC, ':'') ."langue='' DESC," + . 'segments DESC, id_parent' ); - if ($row){ - if (!is_null($type) AND $row['url']==$type){ - array_unshift($url_arbo,$url_segment); + if ($row) { + if (!is_null($type) and $row['url'] == $type) { + array_unshift($url_arbo, $url_segment); $url_segment = $type; $type = null; } $type = $row['type']; $col_id = id_table_objet($type); - + // le plus a droite l'emporte pour des objets presents plusieurs fois dans l'url (ie rubrique) $contexte[$col_id] = $row['id_objet']; $type_parent = ''; - if ($p = url_arbo_parent($type)) - $type_parent=end($p); + if ($p = url_arbo_parent($type)) { + $type_parent = end($p); + } // l'entite la plus a droite l'emporte, si le type de son parent a ete vu // sinon c'est un segment contextuel supplementaire a ignorer // ex : rub1/article/art1/mot1 : il faut ignorer le mot1, la vrai url est celle de l'article if (!$entite - OR $dernier_parent_vu == $type_parent){ - if ($objet_segments==0) + or $dernier_parent_vu == $type_parent + ) { + if ($objet_segments == 0) { $entite = $type; - } - // sinon on change d'objet concerne - else{ + } + } // sinon on change d'objet concerne + else { $objet_segments++; } @@ -576,47 +821,64 @@ function urls_arbo_dist($i, $entite, $args='', $ancre='') { // on note le dernier parent vu de chaque type $parents_vus[$dernier_parent_vu = $type] = $row['id_objet']; - } - else { + } else { // un segment est inconnu - if ($entite=='' OR $entite=='type_urls') { + if ($entite == '' or $entite == 'type_urls') { // on genere une 404 comme il faut si on ne sait pas ou aller - return array(array(),'404'); + return array(array(), '404'); } // ici on a bien reconnu un segment en amont, mais le segment en cours est inconnu // on pourrait renvoyer sur le dernier segment identifie // mais de fait l'url entiere est inconnu : 404 aussi // mais conserver le contexte qui peut contenir un fond d'ou venait peut etre $entite (reecriture urls) - return array($contexte,'404'); + return array($contexte, '404'); } } - if (count($url_arbo_new)){ + if (count($url_arbo_new)) { $caller = debug_backtrace(); $caller = $caller[1]['function']; // si on est appele par un autre module d'url c'est du decodage d'une ancienne URL // ne pas regenerer des segments arbo, mais rediriger vers la nouvelle URL // dans la nouvelle forme - if (strncmp($caller,"urls_",5)==0 AND $caller!=="urls_decoder_url"){ + if (strncmp($caller, 'urls_', 5) == 0 and $caller !== 'urls_decoder_url') { // en absolue, car assembler ne gere pas ce cas particulier include_spip('inc/filtres_mini'); $col_id = id_table_objet($entite); - $url_new = generer_url_entite($contexte[$col_id],$entite); + $url_new = generer_url_entite($contexte[$col_id], $entite, $args); // securite contre redirection infinie - if ($url_new!==$url_propre - AND rtrim($url_new,"/")!==rtrim($url_propre,"/")) + if ($url_new !== $url_propre + and rtrim($url_new, '/') !== rtrim($url_propre, '/') + ) { $url_redirect = url_absolue($url_new); - } - else { - foreach($url_arbo_new as $k=>$o) - if ($s = declarer_url_arbo($o['objet'],$o['id_objet'])) + } + } else { + foreach ($url_arbo_new as $k => $o) { + $c = array( 'langue' => $langue ); + if (isset($parents_vus['rubrique'])) { + $c['id_parent'] = $parents_vus['rubrique']; + } + if ($s = declarer_url_arbo($o['objet'], $o['id_objet'], $c)) { $url_arbo_new[$k] = $s; - else - $url_arbo_new[$k] = implode('/',$o['segment']); - $url_arbo_new = ltrim(implode('/',$url_arbo_new),'/'); - - if ($url_arbo_new!==$url_propre){ - $url_redirect = $url_arbo_new; + } else { + $url_arbo_new[$k] = implode('/', $o['segment']); + } + } + $url_arbo_new = ltrim(implode('/', $url_arbo_new), '/'); + if ($langue and _url_arbo_multilang === true) { + $url_arbo_new = "$langue/" . $url_arbo_new; + if (strpos($args, 'lang=') !== false) { + parse_str($args, $cl); + unset($cl['lang']); + $args = http_build_query($cl); + } + } + if ($url_arbo_new !== $url_propre) { + //var_dump($url_arbo_new,$url_propre); + $url_redirect = _debut_urls_arbo + . $url_arbo_new + . url_arbo_terminaison($entite) + . ($args?"?$args":''); // en absolue, car assembler ne gere pas ce cas particulier include_spip('inc/filtres_mini'); $url_redirect = url_absolue($url_redirect); @@ -625,16 +887,18 @@ function urls_arbo_dist($i, $entite, $args='', $ancre='') { } // gerer le retour depuis des urls propres - if (($entite=='' OR $entite=='type_urls') - AND $GLOBALS['profondeur_url']<=0){ - $urls_anciennes = charger_fonction('propres','urls'); + if (($entite == '' or $entite == 'type_urls') + and $GLOBALS['profondeur_url'] <= 0 + ) { + $urls_anciennes = charger_fonction('propres', 'urls'); + return $urls_anciennes($url_propre, $entite, $contexte); } } - if ($entite=='' OR $entite=='type_urls' /* compat .htaccess 2.0 */) { - if ($type) - $entite = objet_type ($type); - else { + if ($entite == '' or $entite == 'type_urls' /* compat .htaccess 2.0 */) { + if ($type) { + $entite = objet_type($type); + } else { // Si ca ressemble a une URL d'objet, ce n'est pas la home // et on provoque un 404 if (preg_match(',^[^\.]+(\.html)?$,', $url)) { @@ -643,11 +907,9 @@ function urls_arbo_dist($i, $entite, $args='', $ancre='') { } } } - if (!defined('_SET_HTML_BASE')){ - define('_SET_HTML_BASE',1); + if (!defined('_SET_HTML_BASE')) { + define('_SET_HTML_BASE', 1); } return array($contexte, $entite, $url_redirect, null); } - -?>