source: spip-zone/_core_/plugins/urls_etendues/action/editer_url.php

Last change on this file was 113294, checked in by spip.franck@…, 4 months ago

Il parait que le futur c'est maintenant :-D

File size: 11.5 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2019                                                *
7 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8 *                                                                         *
9 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11\***************************************************************************/
12
13if (!defined("_ECRIRE_INC_VERSION")) {
14        return;
15}
16
17function action_editer_url_dist() {
18
19        // Rien a faire ici pour le moment
20        #$securiser_action = charger_fonction('securiser_action', 'inc');
21        #$arg = $securiser_action();
22
23}
24
25/**
26 * Verifier si une langue presumee est valide
27 * - utile pour l'edition manuelle d'une URL ou pour le decodage
28 * @param string $langue
29 * @return bool
30 */
31function url_verifier_langue($langue) {
32        include_spip('inc/lang');
33        if (!match_langue($langue)) {
34                return false;
35        }
36
37        include_spip('inc/lang_liste');
38        $all_langs = array_keys($GLOBALS['codes_langues']);
39        if (!in_array($langue, $all_langs)) {
40                return false;
41        }
42
43        return true;
44}
45
46/**
47 * Nettoyer une URL :
48 * supprimer le html, le rang, extraire les multi, translitterer
49 * @param string $titre
50 * @param int $longueur_maxi
51 * @param int $longueur_min
52 * @param string $separateur
53 * @param string $filtre
54 * @return string
55 */
56function url_nettoyer($titre, $longueur_maxi, $longueur_min = 0, $separateur = '-', $filtre = '') {
57
58        $titre = supprimer_tags(supprimer_numero(extraire_multi($titre)));
59        $url = translitteration($titre);
60
61        if ($filtre) {
62                $url = $filtre($url);
63        }
64
65        // on va convertir tous les caracteres de ponctuation et espaces
66        // a l'exception de l'underscore (_), car on veut le conserver dans l'url
67        $url = str_replace('_', chr(7), $url);
68        $url = @preg_replace(',[[:punct:][:space:]]+,u', ' ', $url);
69        $url = str_replace(chr(7), '_', $url);
70
71        // S'il reste trop de caracteres non latins, les gerer comme wikipedia
72        // avec rawurlencode :
73        if (preg_match_all(",[^a-zA-Z0-9 _]+,", $url, $r, PREG_SET_ORDER)) {
74                foreach ($r as $regs) {
75                        $url = substr_replace($url, rawurlencode($regs[0]),
76                                strpos($url, $regs[0]), strlen($regs[0]));
77                }
78        }
79
80        // S'il reste trop peu, renvoyer vide
81        if (strlen($url) < $longueur_min) {
82                return '';
83        }
84
85        // Sinon couper les mots et les relier par des $separateur
86        $mots = preg_split(",[^a-zA-Z0-9_%]+,", $url);
87        $url = '';
88        foreach ($mots as $mot) {
89                if (!strlen($mot)) {
90                        continue;
91                }
92                $url2 = $url . $separateur . $mot;
93
94                // Si on depasse $longueur_maxi caracteres, s'arreter
95                // ne pas compter 3 caracteres pour %E9 mais un seul
96                $long = preg_replace(',%.,', '', $url2);
97                if (strlen($long) > $longueur_maxi) {
98                        break;
99                }
100
101                $url = $url2;
102        }
103        $url = substr($url, 1);
104
105        // On enregistre en utf-8 dans la base
106        $url = rawurldecode($url);
107
108        if (strlen($url) < $longueur_min) {
109                return '';
110        }
111
112        return $url;
113}
114
115/**
116 * Inserer une URL en base avec multiples controles et gestion des collisions
117 * en essayant d'eviter des problemes de race condition
118 * @param array $set
119 * @param bool $confirmer
120 * @param string $separateur
121 * @return bool
122 */
123function url_insert(&$set, $confirmer, $separateur) {
124        $has_parent = true;
125        # assurer la coherence des champs techniques si non fournis
126        if (!isset($set['id_parent'])) {
127                $has_parent = false;
128                $set['id_parent'] = 0;
129        }
130        if (!isset($set['segments'])) {
131                $set['segments'] = count(explode('/', $set['url']));
132        }
133        if (!isset($set['langue'])) {
134                $set['langue'] = '';
135        }
136        $perma = false;
137        if (isset($set['perma']) and $set['perma']) {
138                unset($set['perma']);
139                $perma = true;
140        }
141        $redate = true;
142
143        # le separateur ne peut pas contenir de /
144        if (strpos($separateur, '/') !== false) {
145                $separateur = "-";
146        }
147
148        // Si l'insertion echoue, c'est une violation d'unicite.
149        $where_urllike = 'url LIKE ' . url_sql_quote_like($set['url']) . " AND NOT(type=" . sql_quote($set['type']) . " AND id_objet=" . intval($set['id_objet']) . ")";
150        $where_thisurl = $where_urllike . ($has_parent ? " AND id_parent=" . intval($set['id_parent']) : "");
151        if (
152                // si pas de parent defini, il faut que cette url soit unique, independamment de id_parent
153                // il faut utiliser un LIKE pour etre case unsensitive en sqlite
154                (!$has_parent and sql_countsel("spip_urls", $where_urllike))
155                or @sql_insertq('spip_urls', $set) <= 0
156        ) {
157
158                // On veut chiper une ancienne adresse ou prendre celle d'un repertoire deja present?
159                if (
160                        (!is_dir(_DIR_RACINE . $set['url']) and !file_exists(_DIR_RACINE . $set['url']))
161                        // un vieux url
162                        and $vieux = sql_fetsel('*', 'spip_urls', $where_thisurl, '', 'perma DESC')
163                        // qui n'est pas permanente
164                        and !$vieux['perma']
165                        // et dont l'objet a une url plus recente
166                        and $courant = sql_fetsel('*', 'spip_urls',
167                                'type=' . sql_quote($vieux['type']) . ' AND id_objet=' . sql_quote($vieux['id_objet'])
168                                . ' AND url<>' . sql_quote($set['url'])
169                                . ' AND date>' . sql_quote($vieux['date']), '', 'date DESC', 1)
170                ) {
171                        if ($confirmer and !_request('ok2')) {
172                                die("Vous voulez chiper l'URL de l'objet " . $courant['type'] . " "
173                                        . $courant['id_objet'] . " qui a maintenant l'url "
174                                        . $courant['url']);
175                        }
176                        $where_thisurl = "url=" . sql_quote($vieux['url']) . " AND id_parent=" . intval($vieux['id_parent']);
177                        // si oui on le chipe
178                        sql_updateq('spip_urls', $set, $where_thisurl);
179                        sql_updateq('spip_urls', array('date' => date('Y-m-d H:i:s')), $where_thisurl);
180                        spip_log("reattribue url " . $vieux['url']
181                                . " de " . $vieux['type'] . "#" . $vieux['id_objet'] . " (parent " . $vieux['id_parent'] . ")"
182                                . " A " . $set['type'] . "#" . $set['id_objet'] . " (parent " . $set['id_parent'] . ")",
183                                "urls" . _LOG_INFO_IMPORTANTE);
184                } // Sinon
185                else {
186
187                        // Soit c'est un Come Back d'une ancienne url propre de l'objet
188                        // Soit c'est un vrai conflit. Rajouter l'ID jusqu'a ce que ca passe,
189                        // mais se casser avant que ca ne casse.
190
191                        // il peut etre du a un changement de casse de l'url simplement
192                        // pour ce cas, on reecrit systematiquement l'url en plus d'actualiser la date
193                        $where = "type=" . sql_quote($set['type'])
194                                . " AND id_objet=" . intval($set['id_objet'])
195                                . " AND id_parent=" . intval($set['id_parent'])
196                                . " AND url LIKE ";
197                        if (
198                                !is_dir(_DIR_RACINE . $set['url']) and !file_exists(_DIR_RACINE . $set['url'])
199                                and $existing = sql_fetsel('*','spip_urls', $where . url_sql_quote_like($set['url']))
200                        ) {
201                                $refresh = array(
202                                        'url' => $set['url'],
203                                        'date' => date('Y-m-d H:i:s'),
204                                );
205                                // si c'est une URL avec langue est qu'ici on a pas de langue, on ecrase
206                                if ($existing['langue']) {
207                                        if (!$set['langue']){
208                                                $refresh['langue'] = '';
209                                        }
210                                        elseif($set['langue'] !== $existing['langue']) {
211                                                $set['url'] .= $separateur . $set['langue'];
212                                                return url_insert_replay($set, $confirmer, $separateur, $has_parent, $perma);
213                                        }
214                                }
215                                // sinon c'est une URL sans langue (generique)
216                                else {
217                                        // si c'est pas une URL perma manuelle,
218                                        // on ignore la langue de cette URL, l'URL generique s'appliquera
219                                        if (!$perma) {
220                                                unset($set['langue']);
221                                        }
222                                        else {
223                                                $refresh['langue'] = $set['langue'];
224                                        }
225                                }
226                                sql_updateq('spip_urls', $refresh, $where . url_sql_quote_like($set['url']));
227                                spip_log("refresh " . $set['type'] . " " . $set['id_objet'].' refresh:'.serialize($refresh), "urls");
228                                $redate = false;
229                        } else {
230                                $set['url'] .= $separateur . $set['id_objet'];
231                                return url_insert_replay($set, $confirmer, $separateur, $has_parent, $perma);
232                        }
233                }
234        }
235
236        $reset = array();
237        // si on a fixe une langue pour cette URL mais qu'il n'y a pas d'URL generique pour cet objet (avec langue='')
238        // on retire la langue car c'est l'URL generique par defaut
239        if (!empty($set['langue'])) {
240                if (!sql_countsel('spip_urls',
241                        "type=" . sql_quote($set['type'])
242                        . " AND id_objet=" . intval($set['id_objet'])
243                        . " AND id_parent=" . intval($set['id_parent'])
244                        . " AND langue=" . sql_quote(''))){
245                        $set['langue'] = $reset['langue'] = '';
246                }
247        } else {
248                $set['langue'] = '';
249        }
250        if ($redate) {
251                $reset['date'] = date('Y-m-d H:i:s');
252        }
253
254        $where_thisurl = 'url=' . sql_quote($set['url']) . " AND id_parent=" . intval($set['id_parent']); // maj
255        if ($reset) {
256                sql_updateq('spip_urls', $reset, $where_thisurl);
257        }
258
259        // si url perma, poser le flag sur la seule url qu'on vient de mettre (au sein de celles qui ont la meme langue)
260        if ($perma) {
261                sql_update('spip_urls', array('perma' => "($where_thisurl)"),
262                        "type=" . sql_quote($set['type']) . " AND id_objet=" . intval($set['id_objet'])." AND langue=" . sql_quote($set['langue']));
263        }
264
265        spip_log("Creation de l'url propre '" . $set['url'] . "' pour "
266                . $set['type'] . " " . $set['id_objet']
267                . " (parent [" . $set['id_parent'] . "] langue [" . $set['langue'] . "] perma [" . ($perma ? "1" : "0") . "])", "urls");
268
269        return true;
270}
271
272/**
273 * Rejouer une insertion qui a echoue avec une url modifiee (rallongee)
274 * on s'assure que la longueur de l'URL n'est pas problematique, et on remet le $set comme il faut
275 * @param array $set
276 * @param bool $confirmer
277 * @param string $separateur
278 * @param bool $has_parent
279 * @param bool $perma
280 * @return bool
281 */
282function url_insert_replay($set, $confirmer, $separateur, $has_parent, $perma) {
283        //var_dump('url_insert_replay');
284        if (strlen($set['url']) > 200) //serveur out ? retourner au mieux
285        {
286                return false;
287        }
288        else {
289                // remettre id_parent et perma comme il faut si besoin
290                if (!$has_parent) {
291                        unset($set['id_parent']);
292                }
293                if ($perma) {
294                        $set['perma'] = true;
295                }
296                //var_dump($set);
297                return url_insert($set, $confirmer, $separateur);
298        }
299}
300
301/**
302 * Faire un quote de l'URL pour une condition LIKE, donc en echapant les caracteres specifiques aux like
303 * @param $url
304 * @return string
305 */
306function url_sql_quote_like($url) {
307        return sql_quote(str_replace(array("%", "_"), array("\\%", "\\_"), $url)) . " ESCAPE " . sql_quote('\\');
308}
309
310/**
311 * Verrouiller une URL
312 * poser le flag sur une unique url d'un objet
313 * (au sein de celles qui ont la meme langue : on peut avoir plusieurs URLs perma, une par langue)
314 *
315 * @param string $url
316 * @param int $id_parent
317 * @param $url
318 */
319function url_verrouiller($url, $id_parent=0) {
320        $where_thisurl = 'url=' . sql_quote($url) . " AND id_parent=" . intval($id_parent);
321        $row = sql_fetsel('*','spip_urls',$where_thisurl);
322
323        // on fait un update unique pour changer toutes les URLs concernees d'un coup
324        if ($row) {
325                sql_update('spip_urls', array('perma' => "($where_thisurl)"),
326                        "type=" . sql_quote($row['type']) . " AND id_objet=" . intval($row['id_objet'])." AND langue=" . sql_quote($row['langue']));
327        }
328}
329
330/**
331 * Supprimer une URL
332 * @param $objet
333 * @param $id_objet
334 * @param string $url
335 * @param int $id_parent
336 */
337function url_delete($objet, $id_objet, $url = "", $id_parent=0) {
338        $where = "id_objet=" . intval($id_objet) . " AND type=" . sql_quote($objet);
339        if (strlen($url)) {
340                $where .= " AND url=" . sql_quote($url) . " AND id_parent=" . intval($id_parent);
341        }
342
343        sql_delete("spip_urls", $where);
344
345        // si on a supprime une seule URL, s'assurer qu'on a toujours au moins une URL avec lang=''
346        $where = "id_objet=" . intval($id_objet) . " AND type=" . sql_quote($objet);
347        if (!$nb = sql_countsel('spip_urls',$where .' AND langue=\'\'')) {
348                if ($last = sql_fetsel('*','spip_urls',$where,'','perma=1 DESC, langue=\'\' DESC, id_parent=0 DESC, date DESC','0,1')) {
349                        sql_updateq('spip_urls',array('langue'=>''),'url='.sql_quote($last['url']) . ' AND id_parent='.intval($last['id_parent']));
350                }
351        }
352}
Note: See TracBrowser for help on using the repository browser.