Completed
Push — master ( 4fa0dc...b74578 )
by cam
01:19
created
ecrire/src/Texte/Collecteur/Liens.php 1 patch
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -15,98 +15,98 @@
 block discarded – undo
15 15
  *    Collecte les raccourcis liens [titre->url] de SPIP
16 16
  */
17 17
 class Liens extends AbstractCollecteur {
18
-	protected static string $markPrefix = 'LIEN';
19
-
20
-	/**
21
-	 * La preg pour découper et collecter les modèles
22
-	 * @var string
23
-	 */
24
-	protected string $preg_lien;
25
-
26
-	public function __construct(?string $preg = null) {
27
-
28
-		// Regexp des raccourcis, aussi utilisee pour la fusion de sauvegarde Spip
29
-		// Laisser passer des paires de crochets pour la balise multi
30
-		// mais refuser plus d'imbrications ou de mauvaises imbrications
31
-		// sinon les crochets ne peuvent plus servir qu'a ce type de raccourci
32
-		$this->preg_lien = ($preg ?: '/\[([^][]*?([[][^]>-]*[]][^][]*)*)->(>?)([^]]*)\]/msS');
33
-	}
34
-
35
-
36
-	/**
37
-	 * Sanitizer une collection d'occurences de liens : il faut sanitizer le href et le texte uniquement
38
-	 *
39
-	 * @param array $collection
40
-	 * @param string $sanitize_callback
41
-	 * @return array
42
-	 */
43
-	protected function sanitizer_collection(array $collection, string $sanitize_callback): array {
44
-		foreach ($collection as &$lien) {
45
-			$t = $sanitize_callback($lien['texte']);
46
-			if ($t !== $lien['texte']) {
47
-				$lien['raw'] = str_replace($lien['texte'], $t, $lien['raw']);
48
-				$lien['texte'] = $t;
49
-			}
50
-			$href = $sanitize_callback($lien['href']);
51
-			if ($href !== $lien['href']) {
52
-				$lien['raw'] = str_replace($lien['href'], $href, $lien['raw']);
53
-				$lien['href'] = $href;
54
-			}
55
-		}
56
-
57
-		return $collection;
58
-	}
59
-
60
-	/**
61
-	 * @param string $texte
62
-	 * @param array $options
63
-	 *   bool $collecter_liens
64
-	 * @return array
65
-	 */
66
-	public function collecter(string $texte, array $options = []): array {
67
-		if (!$texte) {
68
-			return [];
69
-		}
70
-
71
-		$liens = [];
72
-		if (str_contains($texte, '->')) {
73
-			$desechappe_crochets = false;
74
-			// si il y a un crochet ouvrant échappé ou un crochet fermant échappé, les substituer pour les ignorer
75
-			if (str_contains($texte, '\[') || str_contains($texte, '\]')) {
76
-				$texte = str_replace(['\[', '\]'], ["\x1\x5", "\x1\x6"], $texte);
77
-				$desechappe_crochets = true;
78
-			}
79
-
80
-			// collecter les matchs de la preg
81
-			$liens = static::collecteur($texte, '->', '[', $this->preg_lien, empty($options['detecter_presence']) ? 0 : 1);
82
-
83
-			// si on veut seulement detecter la présence, on peut retourner tel quel
84
-			if (empty($options['detecter_presence'])) {
85
-				foreach ($liens as $k => &$lien) {
86
-					$lien['href'] = end($lien['match']);
87
-					$lien['texte'] = $lien['match'][1];
88
-					$lien['ouvrant'] = $lien['match'][3] ?? '';
89
-
90
-					// la mise en lien automatique est passee par la a tort !
91
-					// corrigeons pour eviter d'avoir un <a...> dans un href...
92
-					if (str_starts_with($lien['href'], '<a')) {
93
-						$href = extraire_attribut($lien['href'], 'href');
94
-						// remplacons dans la source qui peut etre reinjectee dans les arguments
95
-						// d'un modele
96
-						$lien['raw'] = str_replace($lien['href'], $href, $lien['raw']);
97
-						// et prenons le href comme la vraie url a linker
98
-						$lien['href'] = $href;
99
-					}
100
-
101
-					if ($desechappe_crochets && str_contains($lien['raw'], "\x1")) {
102
-						$lien['raw'] = str_replace(["\x1\x5", "\x1\x6"], ['[', ']'], $lien['raw']);
103
-						$lien['texte'] = str_replace(["\x1\x5", "\x1\x6"], ['[', ']'], $lien['texte']);
104
-						$lien['href'] = str_replace(["\x1\x5", "\x1\x6"], ['[', ']'], $lien['href']);
105
-					}
106
-				}
107
-			}
108
-		}
109
-
110
-		return $liens;
111
-	}
18
+    protected static string $markPrefix = 'LIEN';
19
+
20
+    /**
21
+     * La preg pour découper et collecter les modèles
22
+     * @var string
23
+     */
24
+    protected string $preg_lien;
25
+
26
+    public function __construct(?string $preg = null) {
27
+
28
+        // Regexp des raccourcis, aussi utilisee pour la fusion de sauvegarde Spip
29
+        // Laisser passer des paires de crochets pour la balise multi
30
+        // mais refuser plus d'imbrications ou de mauvaises imbrications
31
+        // sinon les crochets ne peuvent plus servir qu'a ce type de raccourci
32
+        $this->preg_lien = ($preg ?: '/\[([^][]*?([[][^]>-]*[]][^][]*)*)->(>?)([^]]*)\]/msS');
33
+    }
34
+
35
+
36
+    /**
37
+     * Sanitizer une collection d'occurences de liens : il faut sanitizer le href et le texte uniquement
38
+     *
39
+     * @param array $collection
40
+     * @param string $sanitize_callback
41
+     * @return array
42
+     */
43
+    protected function sanitizer_collection(array $collection, string $sanitize_callback): array {
44
+        foreach ($collection as &$lien) {
45
+            $t = $sanitize_callback($lien['texte']);
46
+            if ($t !== $lien['texte']) {
47
+                $lien['raw'] = str_replace($lien['texte'], $t, $lien['raw']);
48
+                $lien['texte'] = $t;
49
+            }
50
+            $href = $sanitize_callback($lien['href']);
51
+            if ($href !== $lien['href']) {
52
+                $lien['raw'] = str_replace($lien['href'], $href, $lien['raw']);
53
+                $lien['href'] = $href;
54
+            }
55
+        }
56
+
57
+        return $collection;
58
+    }
59
+
60
+    /**
61
+     * @param string $texte
62
+     * @param array $options
63
+     *   bool $collecter_liens
64
+     * @return array
65
+     */
66
+    public function collecter(string $texte, array $options = []): array {
67
+        if (!$texte) {
68
+            return [];
69
+        }
70
+
71
+        $liens = [];
72
+        if (str_contains($texte, '->')) {
73
+            $desechappe_crochets = false;
74
+            // si il y a un crochet ouvrant échappé ou un crochet fermant échappé, les substituer pour les ignorer
75
+            if (str_contains($texte, '\[') || str_contains($texte, '\]')) {
76
+                $texte = str_replace(['\[', '\]'], ["\x1\x5", "\x1\x6"], $texte);
77
+                $desechappe_crochets = true;
78
+            }
79
+
80
+            // collecter les matchs de la preg
81
+            $liens = static::collecteur($texte, '->', '[', $this->preg_lien, empty($options['detecter_presence']) ? 0 : 1);
82
+
83
+            // si on veut seulement detecter la présence, on peut retourner tel quel
84
+            if (empty($options['detecter_presence'])) {
85
+                foreach ($liens as $k => &$lien) {
86
+                    $lien['href'] = end($lien['match']);
87
+                    $lien['texte'] = $lien['match'][1];
88
+                    $lien['ouvrant'] = $lien['match'][3] ?? '';
89
+
90
+                    // la mise en lien automatique est passee par la a tort !
91
+                    // corrigeons pour eviter d'avoir un <a...> dans un href...
92
+                    if (str_starts_with($lien['href'], '<a')) {
93
+                        $href = extraire_attribut($lien['href'], 'href');
94
+                        // remplacons dans la source qui peut etre reinjectee dans les arguments
95
+                        // d'un modele
96
+                        $lien['raw'] = str_replace($lien['href'], $href, $lien['raw']);
97
+                        // et prenons le href comme la vraie url a linker
98
+                        $lien['href'] = $href;
99
+                    }
100
+
101
+                    if ($desechappe_crochets && str_contains($lien['raw'], "\x1")) {
102
+                        $lien['raw'] = str_replace(["\x1\x5", "\x1\x6"], ['[', ']'], $lien['raw']);
103
+                        $lien['texte'] = str_replace(["\x1\x5", "\x1\x6"], ['[', ']'], $lien['texte']);
104
+                        $lien['href'] = str_replace(["\x1\x5", "\x1\x6"], ['[', ']'], $lien['href']);
105
+                    }
106
+                }
107
+            }
108
+        }
109
+
110
+        return $liens;
111
+    }
112 112
 }
Please login to merge, or discard this patch.
ecrire/src/Texte/Collecteur/AbstractCollecteur.php 2 patches
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -12,144 +12,144 @@
 block discarded – undo
12 12
 namespace Spip\Texte\Collecteur;
13 13
 
14 14
 abstract class AbstractCollecteur {
15
-	protected static string $markPrefix = 'COLLECT';
16
-	protected string $markId;
17
-
18
-	/**
19
-	 * Collecteur générique des occurences d'une preg dans un texte avec leurs positions et longueur
20
-	 * @param string $texte
21
-	 *   texte à analyser pour la collecte
22
-	 * @param string $if_chars
23
-	 *   caractere(s) à tester avant de tenter la preg
24
-	 * @param string $start_with
25
-	 *   caractere(s) par lesquels commencent l'expression recherchée (permet de démarrer la preg à la prochaine occurence de cette chaine)
26
-	 * @param string $preg
27
-	 *   preg utilisée pour la collecte
28
-	 * @param int $max_items
29
-	 *   pour limiter le nombre de preg collectée (pour la detection simple de présence par exemple)
30
-	 * @return array
31
-	 */
32
-	protected static function collecteur(string $texte, string $if_chars, string $start_with, string $preg, int $max_items = 0): array {
33
-
34
-		$collection = [];
35
-		$pos = 0;
36
-		while (
37
-			(!$if_chars || str_contains($texte, $if_chars))
38
-			&& ($next = ($start_with ? strpos($texte, $start_with, $pos) : $pos)) !== false
39
-			&& preg_match($preg, $texte, $r, PREG_OFFSET_CAPTURE, $next)
40
-		) {
41
-			$found_pos = $r[0][1];
42
-			$found_length = strlen($r[0][0]);
43
-			$match = [
44
-				'raw' => $r[0][0],
45
-				'match' => array_column($r, 0),
46
-				'pos' => $found_pos,
47
-				'length' => $found_length
48
-			];
49
-
50
-			$collection[] = $match;
51
-
52
-			if ($max_items && count($collection) === $max_items) {
53
-				break;
54
-			}
55
-
56
-			$pos = $match['pos'] + $match['length'];
57
-		}
58
-
59
-		return $collection;
60
-	}
61
-
62
-	/**
63
-	 * Sanitizer une collection d'occurences
64
-	 */
65
-	protected function sanitizer_collection(array $collection, string $sanitize_callback): array {
66
-		foreach ($collection as &$c) {
67
-			$c['raw'] = $sanitize_callback($c['raw']);
68
-		}
69
-
70
-		return $collection;
71
-	}
72
-
73
-	/**
74
-	 * @return array
75
-	 */
76
-	public function collecter(string $texte, array $options = []): array {
77
-		return [];
78
-	}
79
-
80
-	public function detecter($texte): bool {
81
-		if (!empty($this->markId) && str_contains($texte, $this->markId)) {
82
-			return true;
83
-		}
84
-		return !empty($this->collecter($texte, ['detecter_presence' => true]));
85
-	}
86
-
87
-	/**
88
-	 * Echapper les occurences de la collecte par un texte neutre du point de vue HTML
89
-	 *
90
-	 * @see retablir()
91
-	 * @param string $texte
92
-	 * @param array $options
93
-	 *   string $sanitize_callback
94
-	 * @return array
95
-	 *   texte, marqueur utilise pour echapper les modeles
96
-	 */
97
-	public function echapper(string $texte, array $options = []): string {
98
-		if (!function_exists('creer_uniqid')) {
99
-			include_spip('inc/acces');
100
-		}
101
-
102
-		$collection = $this->collecter($texte, $options);
103
-		if (!empty($options['sanitize_callback']) && is_callable($options['sanitize_callback'])) {
104
-			$collection = $this->sanitizer_collection($collection, $options['sanitize_callback']);
105
-		}
106
-
107
-		if ($collection !== []) {
108
-			if (empty($this->markId)) {
109
-				// generer un marqueur qui n'existe pas dans le texte
110
-				do {
111
-					$this->markId = substr(md5(uniqid(static::class, 1)), 0, 7);
112
-					$this->markId = '@|' . static::$markPrefix . $this->markId . '|';
113
-				} while (str_contains($texte, $this->markId));
114
-			}
115
-
116
-			$offset_pos = 0;
117
-			foreach ($collection as $c) {
118
-				$rempl = $this->markId . base64_encode($c['raw']) . '|@';
119
-				$texte = substr_replace($texte, $rempl, $c['pos'] + $offset_pos, $c['length']);
120
-				$offset_pos += strlen($rempl) - $c['length'];
121
-			}
122
-		}
123
-
124
-		return $texte;
125
-	}
126
-
127
-
128
-	/**
129
-	 * Retablir les occurences échappées précédemment
130
-	 *
131
-	 * @see echapper()
132
-	 */
133
-	function retablir(string $texte): string {
134
-
135
-		if (!empty($this->markId)) {
136
-			$lm = strlen($this->markId);
137
-			$pos = 0;
138
-			while (
139
-				($p = strpos($texte, $this->markId, $pos)) !== false
140
-				&& ($end = strpos($texte, '|@', $p + $lm))
141
-			) {
142
-				$base64 = substr($texte, $p + $lm, $end - ($p + $lm));
143
-				if ($c = base64_decode($base64, true)) {
144
-					$texte = substr_replace($texte, $c, $p, $end + 2 - $p);
145
-					$pos = $p + strlen($c);
146
-				}
147
-				else {
148
-					$pos = $end;
149
-				}
150
-			}
151
-		}
152
-
153
-		return $texte;
154
-	}
15
+    protected static string $markPrefix = 'COLLECT';
16
+    protected string $markId;
17
+
18
+    /**
19
+     * Collecteur générique des occurences d'une preg dans un texte avec leurs positions et longueur
20
+     * @param string $texte
21
+     *   texte à analyser pour la collecte
22
+     * @param string $if_chars
23
+     *   caractere(s) à tester avant de tenter la preg
24
+     * @param string $start_with
25
+     *   caractere(s) par lesquels commencent l'expression recherchée (permet de démarrer la preg à la prochaine occurence de cette chaine)
26
+     * @param string $preg
27
+     *   preg utilisée pour la collecte
28
+     * @param int $max_items
29
+     *   pour limiter le nombre de preg collectée (pour la detection simple de présence par exemple)
30
+     * @return array
31
+     */
32
+    protected static function collecteur(string $texte, string $if_chars, string $start_with, string $preg, int $max_items = 0): array {
33
+
34
+        $collection = [];
35
+        $pos = 0;
36
+        while (
37
+            (!$if_chars || str_contains($texte, $if_chars))
38
+            && ($next = ($start_with ? strpos($texte, $start_with, $pos) : $pos)) !== false
39
+            && preg_match($preg, $texte, $r, PREG_OFFSET_CAPTURE, $next)
40
+        ) {
41
+            $found_pos = $r[0][1];
42
+            $found_length = strlen($r[0][0]);
43
+            $match = [
44
+                'raw' => $r[0][0],
45
+                'match' => array_column($r, 0),
46
+                'pos' => $found_pos,
47
+                'length' => $found_length
48
+            ];
49
+
50
+            $collection[] = $match;
51
+
52
+            if ($max_items && count($collection) === $max_items) {
53
+                break;
54
+            }
55
+
56
+            $pos = $match['pos'] + $match['length'];
57
+        }
58
+
59
+        return $collection;
60
+    }
61
+
62
+    /**
63
+     * Sanitizer une collection d'occurences
64
+     */
65
+    protected function sanitizer_collection(array $collection, string $sanitize_callback): array {
66
+        foreach ($collection as &$c) {
67
+            $c['raw'] = $sanitize_callback($c['raw']);
68
+        }
69
+
70
+        return $collection;
71
+    }
72
+
73
+    /**
74
+     * @return array
75
+     */
76
+    public function collecter(string $texte, array $options = []): array {
77
+        return [];
78
+    }
79
+
80
+    public function detecter($texte): bool {
81
+        if (!empty($this->markId) && str_contains($texte, $this->markId)) {
82
+            return true;
83
+        }
84
+        return !empty($this->collecter($texte, ['detecter_presence' => true]));
85
+    }
86
+
87
+    /**
88
+     * Echapper les occurences de la collecte par un texte neutre du point de vue HTML
89
+     *
90
+     * @see retablir()
91
+     * @param string $texte
92
+     * @param array $options
93
+     *   string $sanitize_callback
94
+     * @return array
95
+     *   texte, marqueur utilise pour echapper les modeles
96
+     */
97
+    public function echapper(string $texte, array $options = []): string {
98
+        if (!function_exists('creer_uniqid')) {
99
+            include_spip('inc/acces');
100
+        }
101
+
102
+        $collection = $this->collecter($texte, $options);
103
+        if (!empty($options['sanitize_callback']) && is_callable($options['sanitize_callback'])) {
104
+            $collection = $this->sanitizer_collection($collection, $options['sanitize_callback']);
105
+        }
106
+
107
+        if ($collection !== []) {
108
+            if (empty($this->markId)) {
109
+                // generer un marqueur qui n'existe pas dans le texte
110
+                do {
111
+                    $this->markId = substr(md5(uniqid(static::class, 1)), 0, 7);
112
+                    $this->markId = '@|' . static::$markPrefix . $this->markId . '|';
113
+                } while (str_contains($texte, $this->markId));
114
+            }
115
+
116
+            $offset_pos = 0;
117
+            foreach ($collection as $c) {
118
+                $rempl = $this->markId . base64_encode($c['raw']) . '|@';
119
+                $texte = substr_replace($texte, $rempl, $c['pos'] + $offset_pos, $c['length']);
120
+                $offset_pos += strlen($rempl) - $c['length'];
121
+            }
122
+        }
123
+
124
+        return $texte;
125
+    }
126
+
127
+
128
+    /**
129
+     * Retablir les occurences échappées précédemment
130
+     *
131
+     * @see echapper()
132
+     */
133
+    function retablir(string $texte): string {
134
+
135
+        if (!empty($this->markId)) {
136
+            $lm = strlen($this->markId);
137
+            $pos = 0;
138
+            while (
139
+                ($p = strpos($texte, $this->markId, $pos)) !== false
140
+                && ($end = strpos($texte, '|@', $p + $lm))
141
+            ) {
142
+                $base64 = substr($texte, $p + $lm, $end - ($p + $lm));
143
+                if ($c = base64_decode($base64, true)) {
144
+                    $texte = substr_replace($texte, $c, $p, $end + 2 - $p);
145
+                    $pos = $p + strlen($c);
146
+                }
147
+                else {
148
+                    $pos = $end;
149
+                }
150
+            }
151
+        }
152
+
153
+        return $texte;
154
+    }
155 155
 }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -109,13 +109,13 @@
 block discarded – undo
109 109
 				// generer un marqueur qui n'existe pas dans le texte
110 110
 				do {
111 111
 					$this->markId = substr(md5(uniqid(static::class, 1)), 0, 7);
112
-					$this->markId = '@|' . static::$markPrefix . $this->markId . '|';
112
+					$this->markId = '@|'.static::$markPrefix.$this->markId.'|';
113 113
 				} while (str_contains($texte, $this->markId));
114 114
 			}
115 115
 
116 116
 			$offset_pos = 0;
117 117
 			foreach ($collection as $c) {
118
-				$rempl = $this->markId . base64_encode($c['raw']) . '|@';
118
+				$rempl = $this->markId.base64_encode($c['raw']).'|@';
119 119
 				$texte = substr_replace($texte, $rempl, $c['pos'] + $offset_pos, $c['length']);
120 120
 				$offset_pos += strlen($rempl) - $c['length'];
121 121
 			}
Please login to merge, or discard this patch.
ecrire/src/Sql/Sqlite/Sqlite.php 1 patch
Indentation   +95 added lines, -95 removed lines patch added patch discarded remove patch
@@ -8,112 +8,112 @@
 block discarded – undo
8 8
  **/
9 9
 class Sqlite
10 10
 {
11
-	/** @var Requeteur[] Liste des instances de requêteurs créés */
12
-	public static $requeteurs = [];
13
-	/** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
14
-	public static $transaction_en_cours = [];
11
+    /** @var Requeteur[] Liste des instances de requêteurs créés */
12
+    public static $requeteurs = [];
13
+    /** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
14
+    public static $transaction_en_cours = [];
15 15
 
16 16
 
17
-	/**
18
-	 * Retourne une unique instance du requêteur
19
-	 *
20
-	 * Retourne une instance unique du requêteur pour une connexion SQLite
21
-	 * donnée
22
-	 *
23
-	 * @param string $serveur
24
-	 *    Nom du connecteur
25
-	 * @return Requeteur
26
-	 *    Instance unique du requêteur
27
-	 **/
28
-	public static function requeteur($serveur) {
29
-		if (!isset(static::$requeteurs[$serveur])) {
30
-			static::$requeteurs[$serveur] = new Requeteur($serveur);
31
-		}
17
+    /**
18
+     * Retourne une unique instance du requêteur
19
+     *
20
+     * Retourne une instance unique du requêteur pour une connexion SQLite
21
+     * donnée
22
+     *
23
+     * @param string $serveur
24
+     *    Nom du connecteur
25
+     * @return Requeteur
26
+     *    Instance unique du requêteur
27
+     **/
28
+    public static function requeteur($serveur) {
29
+        if (!isset(static::$requeteurs[$serveur])) {
30
+            static::$requeteurs[$serveur] = new Requeteur($serveur);
31
+        }
32 32
 
33
-		return static::$requeteurs[$serveur];
34
-	}
33
+        return static::$requeteurs[$serveur];
34
+    }
35 35
 
36
-	/**
37
-	 * Prépare le texte d'une requête avant son exécution
38
-	 *
39
-	 * Adapte la requête au format plus ou moins MySQL par un format
40
-	 * compris de SQLite.
41
-	 *
42
-	 * Change les préfixes de tables SPIP par ceux véritables
43
-	 *
44
-	 * @param string $query Requête à préparer
45
-	 * @param string $serveur Nom de la connexion
46
-	 * @return string           Requête préparée
47
-	 */
48
-	public static function traduire_requete($query, $serveur) {
49
-		$requeteur = static::requeteur($serveur);
50
-		$traducteur = new Traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
36
+    /**
37
+     * Prépare le texte d'une requête avant son exécution
38
+     *
39
+     * Adapte la requête au format plus ou moins MySQL par un format
40
+     * compris de SQLite.
41
+     *
42
+     * Change les préfixes de tables SPIP par ceux véritables
43
+     *
44
+     * @param string $query Requête à préparer
45
+     * @param string $serveur Nom de la connexion
46
+     * @return string           Requête préparée
47
+     */
48
+    public static function traduire_requete($query, $serveur) {
49
+        $requeteur = static::requeteur($serveur);
50
+        $traducteur = new Traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
51 51
 
52
-		return $traducteur->traduire_requete();
53
-	}
52
+        return $traducteur->traduire_requete();
53
+    }
54 54
 
55
-	/**
56
-	 * Démarre une transaction
57
-	 *
58
-	 * @param string $serveur Nom de la connexion
59
-	 **/
60
-	public static function demarrer_transaction($serveur) {
61
-		Sqlite::executer_requete('BEGIN TRANSACTION', $serveur);
62
-		Sqlite::$transaction_en_cours[$serveur] = true;
63
-	}
55
+    /**
56
+     * Démarre une transaction
57
+     *
58
+     * @param string $serveur Nom de la connexion
59
+     **/
60
+    public static function demarrer_transaction($serveur) {
61
+        Sqlite::executer_requete('BEGIN TRANSACTION', $serveur);
62
+        Sqlite::$transaction_en_cours[$serveur] = true;
63
+    }
64 64
 
65
-	/**
66
-	 * Exécute la requête donnée
67
-	 *
68
-	 * @param string $query Requête
69
-	 * @param string $serveur Nom de la connexion
70
-	 * @param null|bool $tracer Demander des statistiques (temps) ?
71
-	 **/
72
-	public static function executer_requete($query, $serveur, $tracer = null) {
73
-		$requeteur = Sqlite::requeteur($serveur);
65
+    /**
66
+     * Exécute la requête donnée
67
+     *
68
+     * @param string $query Requête
69
+     * @param string $serveur Nom de la connexion
70
+     * @param null|bool $tracer Demander des statistiques (temps) ?
71
+     **/
72
+    public static function executer_requete($query, $serveur, $tracer = null) {
73
+        $requeteur = Sqlite::requeteur($serveur);
74 74
 
75
-		return $requeteur->executer_requete($query, $tracer);
76
-	}
75
+        return $requeteur->executer_requete($query, $tracer);
76
+    }
77 77
 
78
-	/**
79
-	 * Obtient l'identifiant de la dernière ligne insérée ou modifiée
80
-	 *
81
-	 * @param string $serveur Nom de la connexion
82
-	 * return int                Identifiant
83
-	 **/
84
-	public static function last_insert_id($serveur) {
85
-		$requeteur = Sqlite::requeteur($serveur);
78
+    /**
79
+     * Obtient l'identifiant de la dernière ligne insérée ou modifiée
80
+     *
81
+     * @param string $serveur Nom de la connexion
82
+     * return int                Identifiant
83
+     **/
84
+    public static function last_insert_id($serveur) {
85
+        $requeteur = Sqlite::requeteur($serveur);
86 86
 
87
-		return $requeteur->last_insert_id();
88
-	}
87
+        return $requeteur->last_insert_id();
88
+    }
89 89
 
90
-	/**
91
-	 * Annule une transaction
92
-	 *
93
-	 * @param string $serveur Nom de la connexion
94
-	 **/
95
-	public static function annuler_transaction($serveur) {
96
-		Sqlite::executer_requete('ROLLBACK', $serveur);
97
-		Sqlite::$transaction_en_cours[$serveur] = false;
98
-	}
90
+    /**
91
+     * Annule une transaction
92
+     *
93
+     * @param string $serveur Nom de la connexion
94
+     **/
95
+    public static function annuler_transaction($serveur) {
96
+        Sqlite::executer_requete('ROLLBACK', $serveur);
97
+        Sqlite::$transaction_en_cours[$serveur] = false;
98
+    }
99 99
 
100
-	/**
101
-	 * Termine une transaction
102
-	 *
103
-	 * @param string $serveur Nom de la connexion
104
-	 **/
105
-	public static function finir_transaction($serveur) {
106
-		// si pas de transaction en cours, ne rien faire et le dire
107
-		if (
108
-			!isset(Sqlite::$transaction_en_cours[$serveur])
109
-			|| Sqlite::$transaction_en_cours[$serveur] == false
110
-		) {
111
-			return false;
112
-		}
113
-		// sinon fermer la transaction et retourner true
114
-		Sqlite::executer_requete('COMMIT', $serveur);
115
-		Sqlite::$transaction_en_cours[$serveur] = false;
100
+    /**
101
+     * Termine une transaction
102
+     *
103
+     * @param string $serveur Nom de la connexion
104
+     **/
105
+    public static function finir_transaction($serveur) {
106
+        // si pas de transaction en cours, ne rien faire et le dire
107
+        if (
108
+            !isset(Sqlite::$transaction_en_cours[$serveur])
109
+            || Sqlite::$transaction_en_cours[$serveur] == false
110
+        ) {
111
+            return false;
112
+        }
113
+        // sinon fermer la transaction et retourner true
114
+        Sqlite::executer_requete('COMMIT', $serveur);
115
+        Sqlite::$transaction_en_cours[$serveur] = false;
116 116
 
117
-		return true;
118
-	}
117
+        return true;
118
+    }
119 119
 }
Please login to merge, or discard this patch.
ecrire/src/Sql/Sqlite/PDOStatement.php 1 patch
Indentation   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -6,10 +6,10 @@
 block discarded – undo
6 6
  * Pouvoir retrouver le PDO utilisé pour générer un résultat de requête.
7 7
  */
8 8
 final class PDOStatement extends \PDOStatement {
9
-	private function __construct(private \PDO &$PDO) {
10
-	}
9
+    private function __construct(private \PDO &$PDO) {
10
+    }
11 11
 
12
-	public function getPDO(): \PDO {
13
-		return $this->PDO;
14
-	}
12
+    public function getPDO(): \PDO {
13
+        return $this->PDO;
14
+    }
15 15
 }
Please login to merge, or discard this patch.
ecrire/src/Sql/Sqlite/Requeteur.php 2 patches
Indentation   +105 added lines, -105 removed lines patch added patch discarded remove patch
@@ -13,109 +13,109 @@
 block discarded – undo
13 13
 
14 14
 class Requeteur
15 15
 {
16
-	/** @var string texte de la requête */
17
-	public $query = ''; // la requete
18
-	/** @var string Nom de la connexion */
19
-	public $serveur = '';
20
-	/** @var \PDO|null Identifiant de la connexion SQLite */
21
-	public $link = null;
22
-	/** @var string Prefixe des tables SPIP */
23
-	public $prefixe = '';
24
-	/** @var string Nom de la base de donnée */
25
-	public $db = '';
26
-	/** @var bool Doit-on tracer les requetes (var_profile) ? */
27
-	public $tracer = false; // doit-on tracer les requetes (var_profile)
28
-
29
-	/** @var string Version de SQLite (2 ou 3) */
30
-	public $sqlite_version = '';
31
-
32
-	/**
33
-	 * Constructeur
34
-	 *
35
-	 * @param string $serveur
36
-	 */
37
-	public function __construct($serveur = '') {
38
-		_sqlite_init();
39
-		$this->serveur = strtolower($serveur);
40
-
41
-		if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
42
-			spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
43
-
44
-			return;
45
-		}
46
-
47
-		$this->sqlite_version = _sqlite_is_version('', $this->link);
48
-
49
-		$this->prefixe = $GLOBALS['connexions'][$this->serveur ?: 0]['prefixe'];
50
-		$this->db = $GLOBALS['connexions'][$this->serveur ?: 0]['db'];
51
-
52
-		// tracage des requetes ?
53
-		$this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
54
-	}
55
-
56
-	/**
57
-	 * Lancer la requête transmise et faire le tracage si demandé
58
-	 *
59
-	 * @param string $query
60
-	 *     Requête à exécuter
61
-	 * @param bool|null $tracer
62
-	 *     true pour tracer la requête
63
-	 * @return bool|\PDOStatement|array
64
-	 */
65
-	public function executer_requete($query, $tracer = null) {
66
-		if (is_null($tracer)) {
67
-			$tracer = $this->tracer;
68
-		}
69
-		$err = '';
70
-		$t = 0;
71
-		if ($tracer || defined('_DEBUG_TRACE_QUERIES') && _DEBUG_TRACE_QUERIES) {
72
-			include_spip('public/tracer');
73
-			$t = trace_query_start();
74
-		}
75
-
76
-		# spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
77
-		if ($this->link) {
78
-			// memoriser la derniere erreur PHP vue
79
-			$last_error = (function_exists('error_get_last') ? error_get_last() : '');
80
-			$e = null;
81
-			// sauver la derniere requete
82
-			$GLOBALS['connexions'][$this->serveur ?: 0]['last'] = $query;
83
-			$GLOBALS['connexions'][$this->serveur ?: 0]['total_requetes']++;
84
-
85
-			try {
86
-				$r = $this->link->query($query);
87
-			} catch (\PDOException $e) {
88
-				spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
89
-				$r = false;
90
-			}
91
-
92
-			// loger les warnings/erreurs eventuels de sqlite remontant dans PHP
93
-			if ($e && $e instanceof \PDOException) {
94
-				$err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
95
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
96
-			} elseif (($err = (function_exists('error_get_last') ? error_get_last() : '')) && $err != $last_error) {
97
-				$err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
98
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
99
-			} else {
100
-				$err = '';
101
-			}
102
-		} else {
103
-			$r = false;
104
-		}
105
-
106
-		if (spip_sqlite_errno($this->serveur)) {
107
-			$err .= spip_sqlite_error($query, $this->serveur);
108
-		}
109
-
110
-		return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
111
-	}
112
-
113
-	/**
114
-	 * Obtient l'identifiant de la dernière ligne insérée ou modifiée
115
-	 *
116
-	 * @return string|false
117
-	 **/
118
-	public function last_insert_id() {
119
-		return $this->link->lastInsertId();
120
-	}
16
+    /** @var string texte de la requête */
17
+    public $query = ''; // la requete
18
+    /** @var string Nom de la connexion */
19
+    public $serveur = '';
20
+    /** @var \PDO|null Identifiant de la connexion SQLite */
21
+    public $link = null;
22
+    /** @var string Prefixe des tables SPIP */
23
+    public $prefixe = '';
24
+    /** @var string Nom de la base de donnée */
25
+    public $db = '';
26
+    /** @var bool Doit-on tracer les requetes (var_profile) ? */
27
+    public $tracer = false; // doit-on tracer les requetes (var_profile)
28
+
29
+    /** @var string Version de SQLite (2 ou 3) */
30
+    public $sqlite_version = '';
31
+
32
+    /**
33
+     * Constructeur
34
+     *
35
+     * @param string $serveur
36
+     */
37
+    public function __construct($serveur = '') {
38
+        _sqlite_init();
39
+        $this->serveur = strtolower($serveur);
40
+
41
+        if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
42
+            spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
43
+
44
+            return;
45
+        }
46
+
47
+        $this->sqlite_version = _sqlite_is_version('', $this->link);
48
+
49
+        $this->prefixe = $GLOBALS['connexions'][$this->serveur ?: 0]['prefixe'];
50
+        $this->db = $GLOBALS['connexions'][$this->serveur ?: 0]['db'];
51
+
52
+        // tracage des requetes ?
53
+        $this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
54
+    }
55
+
56
+    /**
57
+     * Lancer la requête transmise et faire le tracage si demandé
58
+     *
59
+     * @param string $query
60
+     *     Requête à exécuter
61
+     * @param bool|null $tracer
62
+     *     true pour tracer la requête
63
+     * @return bool|\PDOStatement|array
64
+     */
65
+    public function executer_requete($query, $tracer = null) {
66
+        if (is_null($tracer)) {
67
+            $tracer = $this->tracer;
68
+        }
69
+        $err = '';
70
+        $t = 0;
71
+        if ($tracer || defined('_DEBUG_TRACE_QUERIES') && _DEBUG_TRACE_QUERIES) {
72
+            include_spip('public/tracer');
73
+            $t = trace_query_start();
74
+        }
75
+
76
+        # spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
77
+        if ($this->link) {
78
+            // memoriser la derniere erreur PHP vue
79
+            $last_error = (function_exists('error_get_last') ? error_get_last() : '');
80
+            $e = null;
81
+            // sauver la derniere requete
82
+            $GLOBALS['connexions'][$this->serveur ?: 0]['last'] = $query;
83
+            $GLOBALS['connexions'][$this->serveur ?: 0]['total_requetes']++;
84
+
85
+            try {
86
+                $r = $this->link->query($query);
87
+            } catch (\PDOException $e) {
88
+                spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
89
+                $r = false;
90
+            }
91
+
92
+            // loger les warnings/erreurs eventuels de sqlite remontant dans PHP
93
+            if ($e && $e instanceof \PDOException) {
94
+                $err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
95
+                spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
96
+            } elseif (($err = (function_exists('error_get_last') ? error_get_last() : '')) && $err != $last_error) {
97
+                $err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
98
+                spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
99
+            } else {
100
+                $err = '';
101
+            }
102
+        } else {
103
+            $r = false;
104
+        }
105
+
106
+        if (spip_sqlite_errno($this->serveur)) {
107
+            $err .= spip_sqlite_error($query, $this->serveur);
108
+        }
109
+
110
+        return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
111
+    }
112
+
113
+    /**
114
+     * Obtient l'identifiant de la dernière ligne insérée ou modifiée
115
+     *
116
+     * @return string|false
117
+     **/
118
+    public function last_insert_id() {
119
+        return $this->link->lastInsertId();
120
+    }
121 121
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -39,7 +39,7 @@  discard block
 block discarded – undo
39 39
 		$this->serveur = strtolower($serveur);
40 40
 
41 41
 		if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
42
-			spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
42
+			spip_log('Aucune connexion sqlite (link)', 'sqlite.'._LOG_ERREUR);
43 43
 
44 44
 			return;
45 45
 		}
@@ -85,17 +85,17 @@  discard block
 block discarded – undo
85 85
 			try {
86 86
 				$r = $this->link->query($query);
87 87
 			} catch (\PDOException $e) {
88
-				spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
88
+				spip_log('PDOException: '.$e->getMessage(), 'sqlite.'._LOG_DEBUG);
89 89
 				$r = false;
90 90
 			}
91 91
 
92 92
 			// loger les warnings/erreurs eventuels de sqlite remontant dans PHP
93 93
 			if ($e && $e instanceof \PDOException) {
94
-				$err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
95
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
94
+				$err = strip_tags($e->getMessage()).' in '.$e->getFile().' line '.$e->getLine();
95
+				spip_log("$err - ".$query, 'sqlite.'._LOG_ERREUR);
96 96
 			} elseif (($err = (function_exists('error_get_last') ? error_get_last() : '')) && $err != $last_error) {
97
-				$err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
98
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
97
+				$err = strip_tags($err['message']).' in '.$err['file'].' line '.$err['line'];
98
+				spip_log("$err - ".$query, 'sqlite.'._LOG_ERREUR);
99 99
 			} else {
100 100
 				$err = '';
101 101
 			}
Please login to merge, or discard this patch.
ecrire/src/Sql/Sqlite/Traducteur.php 2 patches
Indentation   +191 added lines, -191 removed lines patch added patch discarded remove patch
@@ -9,195 +9,195 @@
 block discarded – undo
9 9
  */
10 10
 class Traducteur
11 11
 {
12
-	/** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
13
-	 *
14
-	 * @var array
15
-	 */
16
-	public $textes = [];
17
-
18
-	/**
19
-	 * Constructeur
20
-	 */
21
-	public function __construct(
22
-		/** Requête à préparer */
23
-		public string $query,
24
-		/** Prefixe des tables à utiliser */
25
-		public string $prefixe,
26
-		/** Version SQLite (2 ou 3) */
27
-		public string $sqlite_version
28
-	) {
29
-	}
30
-
31
-	/**
32
-	 * Transformer la requete pour SQLite
33
-	 *
34
-	 * Enlève les textes, transforme la requête pour quelle soit
35
-	 * bien interprétée par SQLite, puis remet les textes
36
-	 * la fonction affecte `$this->query`
37
-	 */
38
-	public function traduire_requete() {
39
-		//
40
-		// 1) Protection des textes en les remplacant par des codes
41
-		//
42
-		// enlever les 'textes' et initialiser avec
43
-		[$this->query, $textes] = query_echappe_textes($this->query);
44
-
45
-		//
46
-		// 2) Corrections de la requete
47
-		//
48
-		// Correction Create Database
49
-		// Create Database -> requete ignoree
50
-		if (str_starts_with($this->query, 'CREATE DATABASE')) {
51
-			spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
52
-			$this->query = 'SELECT 1';
53
-		}
54
-
55
-		// Correction Insert Ignore
56
-		// INSERT IGNORE -> insert (tout court et pas 'insert or replace')
57
-		if (str_starts_with($this->query, 'INSERT IGNORE')) {
58
-			spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
59
-			$this->query = 'INSERT ' . substr($this->query, '13');
60
-		}
61
-
62
-		// Correction des dates avec INTERVAL
63
-		// utiliser sql_date_proche() de preference
64
-		if (str_contains($this->query, 'INTERVAL')) {
65
-			$this->query = preg_replace_callback(
66
-				'/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U',
67
-				fn(array $matches): string => $this->_remplacerDateParTime($matches),
68
-				$this->query
69
-			);
70
-		}
71
-
72
-		if (str_contains($this->query, 'LEFT(')) {
73
-			$this->query = str_replace('LEFT(', '_LEFT(', $this->query);
74
-		}
75
-
76
-		if (str_contains($this->query, 'TIMESTAMPDIFF(')) {
77
-			$this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
78
-		}
79
-
80
-
81
-		// Correction Using
82
-		// USING (non reconnu en sqlite2)
83
-		// problematique car la jointure ne se fait pas du coup.
84
-		if (($this->sqlite_version == 2) && (str_contains($this->query, 'USING'))) {
85
-			spip_log(
86
-				"'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
87
-				'sqlite.' . _LOG_ERREUR
88
-			);
89
-			$this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
90
-		}
91
-
92
-		// Correction Field
93
-		// remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
94
-		if (str_contains($this->query, 'FIELD')) {
95
-			$this->query = preg_replace_callback(
96
-				'/FIELD\s*\(([^\)]*)\)/',
97
-				fn(array $matches): string => $this->_remplacerFieldParCase($matches),
98
-				$this->query
99
-			);
100
-		}
101
-
102
-		// Correction des noms de tables FROM
103
-		// mettre les bons noms de table dans from, update, insert, replace...
104
-		if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
105
-			$suite = strstr($this->query, $regs[0]);
106
-			$this->query = substr($this->query, 0, -strlen($suite));
107
-		} else {
108
-			$suite = '';
109
-		}
110
-		$pref = ($this->prefixe) ? $this->prefixe . '_' : '';
111
-		$this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
112
-
113
-		// Correction zero AS x
114
-		// pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
115
-		// n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
116
-		// il dit que x ne doit pas être un integer dans le order by !
117
-		// on remplace du coup x par vide() dans ce cas uniquement
118
-		//
119
-		// apparait dans public/vertebrer.php et dans le plugin menu aussi qui genere aussi ce genre de requete via un {par num #GET{tri_num}}
120
-		// mais est-ce encore un soucis pour sqlite en 2021 ? (ie commenter le preg_replace marche très bien en sqlite 3.28)
121
-		// on ne remplace que dans ORDER BY ou GROUP BY
122
-		if (str_contains($this->query, '0 AS') && preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
123
-			$suite = strstr($this->query, $regs[0]);
124
-			$this->query = substr($this->query, 0, -strlen($suite));
125
-			// on cherche les noms des x dans 0 AS x
126
-			// on remplace dans $suite le nom par vide()
127
-			preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
128
-			foreach ($matches[1] as $m) {
129
-				if (str_contains($suite, $m)) {
130
-					$suite = preg_replace(",\b$m\b,", 'VIDE()', $suite);
131
-				}
132
-			}
133
-			$this->query .= $suite;
134
-		}
135
-
136
-		// Correction possible des divisions entieres
137
-		// Le standard SQL (lequel? ou?) semble indiquer que
138
-		// a/b=c doit donner c entier si a et b sont entiers 4/3=1.
139
-		// C'est ce que retournent effectivement SQL Server et SQLite
140
-		// Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
141
-		//
142
-		// On peut forcer la conversion en multipliant par 1.0 avant la division
143
-		// /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
144
-		// cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
145
-		//     http://www.sqlite.org/cvstrac/tktview?tn=3202
146
-		// (4*1.0/3) n'est pas rendu dans ce cas !
147
-		# $this->query = str_replace('/','* 1.00 / ',$this->query);
148
-
149
-
150
-		// Correction critere REGEXP, non reconnu en sqlite2
151
-		if (($this->sqlite_version == 2) && (str_contains($this->query, 'REGEXP'))) {
152
-			$this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
153
-		}
154
-
155
-		//
156
-		// 3) Remise en place des textes d'origine
157
-		//
158
-		// Correction Antiquotes et echappements
159
-		// ` => rien
160
-		if (str_contains($this->query, '`')) {
161
-			$this->query = str_replace('`', '', $this->query);
162
-		}
163
-
164
-		$this->query = query_reinjecte_textes($this->query, $textes);
165
-
166
-		return $this->query;
167
-	}
168
-
169
-	/**
170
-	 * Callback pour remplacer `DATE_` / `INTERVAL`
171
-	 * par `DATE ... strtotime`
172
-	 *
173
-	 * @param array $matches Captures
174
-	 * @return string texte de date compris par SQLite
175
-	 */
176
-	public function _remplacerDateParTime($matches) {
177
-		$op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
178
-
179
-		return "datetime$matches[2] '$op$matches[3] $matches[4]')";
180
-	}
181
-
182
-	/**
183
-	 * Callback pour remplacer `FIELD(table,i,j,k...)`
184
-	 * par `CASE WHEN table=i THEN n ... ELSE 0 END`
185
-	 *
186
-	 * @param array $matches Captures
187
-	 * @return string texte de liste ordonnée compris par SQLite
188
-	 */
189
-	public function _remplacerFieldParCase($matches) {
190
-		$fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
191
-		$t = explode(',', $fields);
192
-		$index = array_shift($t);
193
-
194
-		$res = '';
195
-		$n = 0;
196
-		foreach ($t as $v) {
197
-			$n++;
198
-			$res .= "\nWHEN $index=$v THEN $n";
199
-		}
200
-
201
-		return "CASE $res ELSE 0 END ";
202
-	}
12
+    /** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
13
+     *
14
+     * @var array
15
+     */
16
+    public $textes = [];
17
+
18
+    /**
19
+     * Constructeur
20
+     */
21
+    public function __construct(
22
+        /** Requête à préparer */
23
+        public string $query,
24
+        /** Prefixe des tables à utiliser */
25
+        public string $prefixe,
26
+        /** Version SQLite (2 ou 3) */
27
+        public string $sqlite_version
28
+    ) {
29
+    }
30
+
31
+    /**
32
+     * Transformer la requete pour SQLite
33
+     *
34
+     * Enlève les textes, transforme la requête pour quelle soit
35
+     * bien interprétée par SQLite, puis remet les textes
36
+     * la fonction affecte `$this->query`
37
+     */
38
+    public function traduire_requete() {
39
+        //
40
+        // 1) Protection des textes en les remplacant par des codes
41
+        //
42
+        // enlever les 'textes' et initialiser avec
43
+        [$this->query, $textes] = query_echappe_textes($this->query);
44
+
45
+        //
46
+        // 2) Corrections de la requete
47
+        //
48
+        // Correction Create Database
49
+        // Create Database -> requete ignoree
50
+        if (str_starts_with($this->query, 'CREATE DATABASE')) {
51
+            spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
52
+            $this->query = 'SELECT 1';
53
+        }
54
+
55
+        // Correction Insert Ignore
56
+        // INSERT IGNORE -> insert (tout court et pas 'insert or replace')
57
+        if (str_starts_with($this->query, 'INSERT IGNORE')) {
58
+            spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
59
+            $this->query = 'INSERT ' . substr($this->query, '13');
60
+        }
61
+
62
+        // Correction des dates avec INTERVAL
63
+        // utiliser sql_date_proche() de preference
64
+        if (str_contains($this->query, 'INTERVAL')) {
65
+            $this->query = preg_replace_callback(
66
+                '/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U',
67
+                fn(array $matches): string => $this->_remplacerDateParTime($matches),
68
+                $this->query
69
+            );
70
+        }
71
+
72
+        if (str_contains($this->query, 'LEFT(')) {
73
+            $this->query = str_replace('LEFT(', '_LEFT(', $this->query);
74
+        }
75
+
76
+        if (str_contains($this->query, 'TIMESTAMPDIFF(')) {
77
+            $this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
78
+        }
79
+
80
+
81
+        // Correction Using
82
+        // USING (non reconnu en sqlite2)
83
+        // problematique car la jointure ne se fait pas du coup.
84
+        if (($this->sqlite_version == 2) && (str_contains($this->query, 'USING'))) {
85
+            spip_log(
86
+                "'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
87
+                'sqlite.' . _LOG_ERREUR
88
+            );
89
+            $this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
90
+        }
91
+
92
+        // Correction Field
93
+        // remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
94
+        if (str_contains($this->query, 'FIELD')) {
95
+            $this->query = preg_replace_callback(
96
+                '/FIELD\s*\(([^\)]*)\)/',
97
+                fn(array $matches): string => $this->_remplacerFieldParCase($matches),
98
+                $this->query
99
+            );
100
+        }
101
+
102
+        // Correction des noms de tables FROM
103
+        // mettre les bons noms de table dans from, update, insert, replace...
104
+        if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
105
+            $suite = strstr($this->query, $regs[0]);
106
+            $this->query = substr($this->query, 0, -strlen($suite));
107
+        } else {
108
+            $suite = '';
109
+        }
110
+        $pref = ($this->prefixe) ? $this->prefixe . '_' : '';
111
+        $this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
112
+
113
+        // Correction zero AS x
114
+        // pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
115
+        // n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
116
+        // il dit que x ne doit pas être un integer dans le order by !
117
+        // on remplace du coup x par vide() dans ce cas uniquement
118
+        //
119
+        // apparait dans public/vertebrer.php et dans le plugin menu aussi qui genere aussi ce genre de requete via un {par num #GET{tri_num}}
120
+        // mais est-ce encore un soucis pour sqlite en 2021 ? (ie commenter le preg_replace marche très bien en sqlite 3.28)
121
+        // on ne remplace que dans ORDER BY ou GROUP BY
122
+        if (str_contains($this->query, '0 AS') && preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
123
+            $suite = strstr($this->query, $regs[0]);
124
+            $this->query = substr($this->query, 0, -strlen($suite));
125
+            // on cherche les noms des x dans 0 AS x
126
+            // on remplace dans $suite le nom par vide()
127
+            preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
128
+            foreach ($matches[1] as $m) {
129
+                if (str_contains($suite, $m)) {
130
+                    $suite = preg_replace(",\b$m\b,", 'VIDE()', $suite);
131
+                }
132
+            }
133
+            $this->query .= $suite;
134
+        }
135
+
136
+        // Correction possible des divisions entieres
137
+        // Le standard SQL (lequel? ou?) semble indiquer que
138
+        // a/b=c doit donner c entier si a et b sont entiers 4/3=1.
139
+        // C'est ce que retournent effectivement SQL Server et SQLite
140
+        // Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
141
+        //
142
+        // On peut forcer la conversion en multipliant par 1.0 avant la division
143
+        // /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
144
+        // cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
145
+        //     http://www.sqlite.org/cvstrac/tktview?tn=3202
146
+        // (4*1.0/3) n'est pas rendu dans ce cas !
147
+        # $this->query = str_replace('/','* 1.00 / ',$this->query);
148
+
149
+
150
+        // Correction critere REGEXP, non reconnu en sqlite2
151
+        if (($this->sqlite_version == 2) && (str_contains($this->query, 'REGEXP'))) {
152
+            $this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
153
+        }
154
+
155
+        //
156
+        // 3) Remise en place des textes d'origine
157
+        //
158
+        // Correction Antiquotes et echappements
159
+        // ` => rien
160
+        if (str_contains($this->query, '`')) {
161
+            $this->query = str_replace('`', '', $this->query);
162
+        }
163
+
164
+        $this->query = query_reinjecte_textes($this->query, $textes);
165
+
166
+        return $this->query;
167
+    }
168
+
169
+    /**
170
+     * Callback pour remplacer `DATE_` / `INTERVAL`
171
+     * par `DATE ... strtotime`
172
+     *
173
+     * @param array $matches Captures
174
+     * @return string texte de date compris par SQLite
175
+     */
176
+    public function _remplacerDateParTime($matches) {
177
+        $op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
178
+
179
+        return "datetime$matches[2] '$op$matches[3] $matches[4]')";
180
+    }
181
+
182
+    /**
183
+     * Callback pour remplacer `FIELD(table,i,j,k...)`
184
+     * par `CASE WHEN table=i THEN n ... ELSE 0 END`
185
+     *
186
+     * @param array $matches Captures
187
+     * @return string texte de liste ordonnée compris par SQLite
188
+     */
189
+    public function _remplacerFieldParCase($matches) {
190
+        $fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
191
+        $t = explode(',', $fields);
192
+        $index = array_shift($t);
193
+
194
+        $res = '';
195
+        $n = 0;
196
+        foreach ($t as $v) {
197
+            $n++;
198
+            $res .= "\nWHEN $index=$v THEN $n";
199
+        }
200
+
201
+        return "CASE $res ELSE 0 END ";
202
+    }
203 203
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -48,15 +48,15 @@  discard block
 block discarded – undo
48 48
 		// Correction Create Database
49 49
 		// Create Database -> requete ignoree
50 50
 		if (str_starts_with($this->query, 'CREATE DATABASE')) {
51
-			spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
51
+			spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.'._LOG_AVERTISSEMENT);
52 52
 			$this->query = 'SELECT 1';
53 53
 		}
54 54
 
55 55
 		// Correction Insert Ignore
56 56
 		// INSERT IGNORE -> insert (tout court et pas 'insert or replace')
57 57
 		if (str_starts_with($this->query, 'INSERT IGNORE')) {
58
-			spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
59
-			$this->query = 'INSERT ' . substr($this->query, '13');
58
+			spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.'._LOG_DEBUG);
59
+			$this->query = 'INSERT '.substr($this->query, '13');
60 60
 		}
61 61
 
62 62
 		// Correction des dates avec INTERVAL
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
 		if (($this->sqlite_version == 2) && (str_contains($this->query, 'USING'))) {
85 85
 			spip_log(
86 86
 				"'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
87
-				'sqlite.' . _LOG_ERREUR
87
+				'sqlite.'._LOG_ERREUR
88 88
 			);
89 89
 			$this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
90 90
 		}
@@ -107,8 +107,8 @@  discard block
 block discarded – undo
107 107
 		} else {
108 108
 			$suite = '';
109 109
 		}
110
-		$pref = ($this->prefixe) ? $this->prefixe . '_' : '';
111
-		$this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
110
+		$pref = ($this->prefixe) ? $this->prefixe.'_' : '';
111
+		$this->query = preg_replace('/([,\s])spip_/S', '\1'.$pref, $this->query).$suite;
112 112
 
113 113
 		// Correction zero AS x
114 114
 		// pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
Please login to merge, or discard this patch.
ecrire/src/Compilateur/Noeud/Idiome.php 1 patch
Indentation   +81 added lines, -81 removed lines patch added patch discarded remove patch
@@ -7,85 +7,85 @@
 block discarded – undo
7 7
  **/
8 8
 class Idiome
9 9
 {
10
-	/** Type de noeud */
11
-	public string $type = 'idiome';
12
-
13
-	/** Clé de traduction demandée. Exemple 'item_oui' */
14
-	public string $nom_champ = '';
15
-
16
-	/** Module de langue où chercher la clé de traduction. Exemple 'medias' */
17
-	public string $module = '';
18
-
19
-	/** Arguments à passer à la chaîne */
20
-	public array $arg = [];
21
-
22
-	/**
23
-	 * Filtres à appliquer au résultat
24
-	 *
25
-	 *
26
-	 * * FIXME: type unique.
27
-	 * @var false|array
28
-	 *     - false: erreur de syntaxe
29
-	 */
30
-	public $param = [];
31
-
32
-	/** Source des filtres (compatibilité) (?) */
33
-	public array $fonctions = [];
34
-
35
-	/**
36
-	 * Inutilisé, propriété générique de l'AST
37
-	 *
38
-	 * @var string|array
39
-	 */
40
-	public $avant = '';
41
-
42
-	/**
43
-	 * Inutilisé, propriété générique de l'AST
44
-	 *
45
-	 * @var string|array
46
-	 */
47
-	public $apres = '';
48
-
49
-	/** Identifiant de la boucle */
50
-	public string $id_boucle = '';
51
-
52
-	/**
53
-	 * AST du squelette, liste de toutes les boucles
54
-	 *
55
-	 * @var Boucle[]
56
-	 */
57
-	public array $boucles;
58
-
59
-	/** Alias de table d'application de la requête ou nom complet de la table SQL */
60
-	public ?string $type_requete = null;
61
-
62
-	/** Résultat de la compilation: toujours une expression PHP */
63
-	public string $code = '';
64
-
65
-	/**
66
-	 * Interdire les scripts
67
-	 *
68
-	 * @see interdire_scripts()
69
-	 */
70
-	public bool $interdire_scripts = false;
71
-
72
-	/**
73
-	 * Description du squelette
74
-	 *
75
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
76
-	 *
77
-	 * Peut contenir les index :
78
-	 * - nom : Nom du fichier de cache
79
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
80
-	 * - sourcefile : Chemin du squelette
81
-	 * - squelette : Code du squelette
82
-	 * - id_mere : Identifiant de la boucle parente
83
-	 * - documents : Pour embed et img dans les textes
84
-	 * - session : Pour un cache sessionné par auteur
85
-	 * - niv : Niveau de tabulation
86
-	 */
87
-	public array $descr = [];
88
-
89
-	/** Numéro de ligne dans le code source du squelette */
90
-	public int $ligne = 0;
10
+    /** Type de noeud */
11
+    public string $type = 'idiome';
12
+
13
+    /** Clé de traduction demandée. Exemple 'item_oui' */
14
+    public string $nom_champ = '';
15
+
16
+    /** Module de langue où chercher la clé de traduction. Exemple 'medias' */
17
+    public string $module = '';
18
+
19
+    /** Arguments à passer à la chaîne */
20
+    public array $arg = [];
21
+
22
+    /**
23
+     * Filtres à appliquer au résultat
24
+     *
25
+     *
26
+     * * FIXME: type unique.
27
+     * @var false|array
28
+     *     - false: erreur de syntaxe
29
+     */
30
+    public $param = [];
31
+
32
+    /** Source des filtres (compatibilité) (?) */
33
+    public array $fonctions = [];
34
+
35
+    /**
36
+     * Inutilisé, propriété générique de l'AST
37
+     *
38
+     * @var string|array
39
+     */
40
+    public $avant = '';
41
+
42
+    /**
43
+     * Inutilisé, propriété générique de l'AST
44
+     *
45
+     * @var string|array
46
+     */
47
+    public $apres = '';
48
+
49
+    /** Identifiant de la boucle */
50
+    public string $id_boucle = '';
51
+
52
+    /**
53
+     * AST du squelette, liste de toutes les boucles
54
+     *
55
+     * @var Boucle[]
56
+     */
57
+    public array $boucles;
58
+
59
+    /** Alias de table d'application de la requête ou nom complet de la table SQL */
60
+    public ?string $type_requete = null;
61
+
62
+    /** Résultat de la compilation: toujours une expression PHP */
63
+    public string $code = '';
64
+
65
+    /**
66
+     * Interdire les scripts
67
+     *
68
+     * @see interdire_scripts()
69
+     */
70
+    public bool $interdire_scripts = false;
71
+
72
+    /**
73
+     * Description du squelette
74
+     *
75
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
76
+     *
77
+     * Peut contenir les index :
78
+     * - nom : Nom du fichier de cache
79
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
80
+     * - sourcefile : Chemin du squelette
81
+     * - squelette : Code du squelette
82
+     * - id_mere : Identifiant de la boucle parente
83
+     * - documents : Pour embed et img dans les textes
84
+     * - session : Pour un cache sessionné par auteur
85
+     * - niv : Niveau de tabulation
86
+     */
87
+    public array $descr = [];
88
+
89
+    /** Numéro de ligne dans le code source du squelette */
90
+    public int $ligne = 0;
91 91
 }
Please login to merge, or discard this patch.
ecrire/src/Compilateur/Noeud/Champ.php 1 patch
Indentation   +100 added lines, -100 removed lines patch added patch discarded remove patch
@@ -7,104 +7,104 @@
 block discarded – undo
7 7
  */
8 8
 class Champ
9 9
 {
10
-	/** Type de noeud */
11
-	public string $type = 'champ';
12
-
13
-	/** Nom du champ demandé. Exemple 'ID_ARTICLE' */
14
-	public ?string $nom_champ = null;
15
-
16
-	/** Identifiant de la boucle parente si explicité */
17
-	public ?string $nom_boucle = '';
18
-
19
-	/**
20
-	 * Partie optionnelle avant
21
-	 *
22
-	 * @var null|string|array
23
-	 */
24
-	public $avant;
25
-
26
-	/**
27
-	 * Partie optionnelle après
28
-	 *
29
-	 * @var null|string|array
30
-	 */
31
-	public $apres;
32
-
33
-	/**
34
-	 * Étoiles : annuler des automatismes
35
-	 *
36
-	 * - '*' annule les filtres automatiques
37
-	 * - '**' annule en plus les protections de scripts
38
-	 *
39
-	 * FIXME: type unique.
40
-	 */
41
-	public ?string $etoile = '';
42
-
43
-	/**
44
-	 * Arguments et filtres explicites sur la balise
45
-	 *
46
-	 * - $param[0] contient les arguments de la balise
47
-	 * - $param[1..n] contient les filtres à appliquer à la balise
48
-	 *
49
-	 * FIXME: type unique.
50
-	 * @var false|array
51
-	 *     - false: erreur de syntaxe
52
-	 */
53
-	public $param = [];
54
-
55
-	/** Source des filtres (compatibilité) (?) */
56
-	public array $fonctions = [];
57
-
58
-	/**
59
-	 * Identifiant de la boucle
60
-	 *
61
-	 * @var string
62
-	 */
63
-	public $id_boucle = '';
64
-
65
-	/**
66
-	 * AST du squelette, liste de toutes les boucles
67
-	 *
68
-	 * @var Boucle[]
69
-	 */
70
-	public array $boucles;
71
-
72
-	/** Alias de table d'application de la requête ou nom complet de la table SQL */
73
-	public ?string $type_requete = null;
74
-
75
-	/** Résultat de la compilation: toujours une expression PHP */
76
-	public string $code = '';
77
-
78
-	/**
79
-	 * Interdire les scripts
80
-	 *
81
-	 * false si on est sûr de cette balise
82
-	 *
83
-	 * @see interdire_scripts()
84
-	 */
85
-	public bool $interdire_scripts = true;
86
-
87
-	/**
88
-	 * Description du squelette
89
-	 *
90
-	 * Sert pour la gestion d'erreur et la production de code dependant du contexte
91
-	 *
92
-	 * Peut contenir les index :
93
-	 *
94
-	 * - nom : Nom du fichier de cache
95
-	 * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
96
-	 * - sourcefile : Chemin du squelette
97
-	 * - squelette : Code du squelette
98
-	 * - id_mere : Identifiant de la boucle parente
99
-	 * - documents : Pour embed et img dans les textes
100
-	 * - session : Pour un cache sessionné par auteur
101
-	 * - niv : Niveau de tabulation
102
-	 */
103
-	public array $descr = [];
104
-
105
-	/** Numéro de ligne dans le code source du squelette*/
106
-	public int $ligne = 0;
107
-
108
-	/** Drapeau pour reperer les balises calculées par une fonction explicite */
109
-	public bool $balise_calculee = false;
10
+    /** Type de noeud */
11
+    public string $type = 'champ';
12
+
13
+    /** Nom du champ demandé. Exemple 'ID_ARTICLE' */
14
+    public ?string $nom_champ = null;
15
+
16
+    /** Identifiant de la boucle parente si explicité */
17
+    public ?string $nom_boucle = '';
18
+
19
+    /**
20
+     * Partie optionnelle avant
21
+     *
22
+     * @var null|string|array
23
+     */
24
+    public $avant;
25
+
26
+    /**
27
+     * Partie optionnelle après
28
+     *
29
+     * @var null|string|array
30
+     */
31
+    public $apres;
32
+
33
+    /**
34
+     * Étoiles : annuler des automatismes
35
+     *
36
+     * - '*' annule les filtres automatiques
37
+     * - '**' annule en plus les protections de scripts
38
+     *
39
+     * FIXME: type unique.
40
+     */
41
+    public ?string $etoile = '';
42
+
43
+    /**
44
+     * Arguments et filtres explicites sur la balise
45
+     *
46
+     * - $param[0] contient les arguments de la balise
47
+     * - $param[1..n] contient les filtres à appliquer à la balise
48
+     *
49
+     * FIXME: type unique.
50
+     * @var false|array
51
+     *     - false: erreur de syntaxe
52
+     */
53
+    public $param = [];
54
+
55
+    /** Source des filtres (compatibilité) (?) */
56
+    public array $fonctions = [];
57
+
58
+    /**
59
+     * Identifiant de la boucle
60
+     *
61
+     * @var string
62
+     */
63
+    public $id_boucle = '';
64
+
65
+    /**
66
+     * AST du squelette, liste de toutes les boucles
67
+     *
68
+     * @var Boucle[]
69
+     */
70
+    public array $boucles;
71
+
72
+    /** Alias de table d'application de la requête ou nom complet de la table SQL */
73
+    public ?string $type_requete = null;
74
+
75
+    /** Résultat de la compilation: toujours une expression PHP */
76
+    public string $code = '';
77
+
78
+    /**
79
+     * Interdire les scripts
80
+     *
81
+     * false si on est sûr de cette balise
82
+     *
83
+     * @see interdire_scripts()
84
+     */
85
+    public bool $interdire_scripts = true;
86
+
87
+    /**
88
+     * Description du squelette
89
+     *
90
+     * Sert pour la gestion d'erreur et la production de code dependant du contexte
91
+     *
92
+     * Peut contenir les index :
93
+     *
94
+     * - nom : Nom du fichier de cache
95
+     * - gram : Nom de la grammaire du squelette (détermine le phraseur à utiliser)
96
+     * - sourcefile : Chemin du squelette
97
+     * - squelette : Code du squelette
98
+     * - id_mere : Identifiant de la boucle parente
99
+     * - documents : Pour embed et img dans les textes
100
+     * - session : Pour un cache sessionné par auteur
101
+     * - niv : Niveau de tabulation
102
+     */
103
+    public array $descr = [];
104
+
105
+    /** Numéro de ligne dans le code source du squelette*/
106
+    public int $ligne = 0;
107
+
108
+    /** Drapeau pour reperer les balises calculées par une fonction explicite */
109
+    public bool $balise_calculee = false;
110 110
 }
Please login to merge, or discard this patch.
ecrire/src/Compilateur/Noeud/Critere.php 1 patch
Indentation   +28 added lines, -28 removed lines patch added patch discarded remove patch
@@ -8,32 +8,32 @@
 block discarded – undo
8 8
  * Sous-noeud de Boucle
9 9
  **/
10 10
 class Critere {
11
-	/** Type de noeud */
12
-	public string $type = 'critere';
13
-
14
-	/** Opérateur (>, <, >=, IN, ...) */
15
-	public ?string $op = null;
16
-
17
-	/** Présence d'une négation (truc !op valeur) */
18
-	public bool $not = false;
19
-
20
-	/** Présence d'une exclusion (!truc op valeur) */
21
-	public string $exclus = '';
22
-
23
-	/** Présence d'une condition dans le critère (truc ?) */
24
-	public bool $cond = false;
25
-
26
-	/**
27
-	 * Paramètres du critère
28
-	 * - $param[0] : élément avant l'opérateur
29
-	 * - $param[1..n] : éléments après l'opérateur
30
-	 *
31
-	 * FIXME: type unique.
32
-	 * @var false|array
33
-	 *     - false: erreur de syntaxe
34
-	 */
35
-	public $param = [];
36
-
37
-	/** Numéro de ligne dans le code source du squelette */
38
-	public int $ligne = 0;
11
+    /** Type de noeud */
12
+    public string $type = 'critere';
13
+
14
+    /** Opérateur (>, <, >=, IN, ...) */
15
+    public ?string $op = null;
16
+
17
+    /** Présence d'une négation (truc !op valeur) */
18
+    public bool $not = false;
19
+
20
+    /** Présence d'une exclusion (!truc op valeur) */
21
+    public string $exclus = '';
22
+
23
+    /** Présence d'une condition dans le critère (truc ?) */
24
+    public bool $cond = false;
25
+
26
+    /**
27
+     * Paramètres du critère
28
+     * - $param[0] : élément avant l'opérateur
29
+     * - $param[1..n] : éléments après l'opérateur
30
+     *
31
+     * FIXME: type unique.
32
+     * @var false|array
33
+     *     - false: erreur de syntaxe
34
+     */
35
+    public $param = [];
36
+
37
+    /** Numéro de ligne dans le code source du squelette */
38
+    public int $ligne = 0;
39 39
 }
Please login to merge, or discard this patch.