diff --git a/ecrire/base/create.php b/ecrire/base/create.php
index f6f79e51f8ff99e62a7e2a1ba6954187fb90e7bf..c7e8fb717382e9f7399aae2008c521e770e70f80 100644
--- a/ecrire/base/create.php
+++ b/ecrire/base/create.php
@@ -40,8 +40,8 @@ function base_determine_autoinc($table, $desc = []) {
 	} else {
 		// essayer de faire au mieux !
 		$autoinc = (isset($desc['key']['PRIMARY KEY'])
-			and strpos($desc['key']['PRIMARY KEY'], ',') === false
-			and strpos($desc['field'][$desc['key']['PRIMARY KEY']], 'default') === false);
+			and !str_contains($desc['key']['PRIMARY KEY'], ',')
+			and !str_contains($desc['field'][$desc['key']['PRIMARY KEY']], 'default'));
 	}
 
 	return $autoinc;
diff --git a/ecrire/base/repair.php b/ecrire/base/repair.php
index bd416bb41a549001274d85baac4bfe65a2b7f45e..ea9ad6f0f401545417a1d7fe82f8ae7e0a1c53df 100644
--- a/ecrire/base/repair.php
+++ b/ecrire/base/repair.php
@@ -106,7 +106,7 @@ function admin_repair_tables() {
 				' ',
 				(is_resource($result_repair) or is_object($result_repair)) ? sql_fetch($result_repair) : $result_repair
 			) . ' '
-			and strpos($msg, ' OK ') === false
+			and !str_contains($msg, ' OK ')
 		) {
 			$class = " class='notice'";
 			$m .= '<br /><tt>' . spip_htmlentities($msg) . "</tt>\n";
diff --git a/ecrire/inc/actions.php b/ecrire/inc/actions.php
index 425e29c4a108dd44969dfb88a62c942a2cf04dd5..9e90ddb9b9cb6b25ee63828dea1966e1247a590e 100644
--- a/ecrire/inc/actions.php
+++ b/ecrire/inc/actions.php
@@ -128,7 +128,7 @@ function ajax_retour($corps, $content_type = null): void {
 	if (is_null($content_type) or $content_type === true) {
 		$xml = true;
 		$content_type = 'text/html';
-	} elseif (!$content_type or !is_string($content_type) or strpos($content_type, '/') === false) {
+	} elseif (!$content_type or !is_string($content_type) or !str_contains($content_type, '/')) {
 		$content_type = 'text/html';
 	}
 
diff --git a/ecrire/inc/charsets.php b/ecrire/inc/charsets.php
index b43e81d77f38295806cfbdb776fe5fb9d589933c..5ceb38298fc08fb090b7a81e4ae7965026d29bc1 100644
--- a/ecrire/inc/charsets.php
+++ b/ecrire/inc/charsets.php
@@ -973,7 +973,7 @@ function transcoder_page($texte, $headers = ''): string {
 		// charset precise par le contenu (html)
 		preg_match(',<(meta|html|body)[^>]*charset[^>]*=[^>]*([#-_a-z0-9]+?),UimsS', $texte, $regs)
 		# eviter toute balise SPIP tel que #CHARSET ou #CONFIG d'un squelette
-		and false === strpos($regs[2], '#')
+		and !str_contains($regs[2], '#')
 		and $tmp = trim(strtolower($regs[2]))
 	) {
 		$charset = $tmp;
diff --git a/ecrire/inc/config.php b/ecrire/inc/config.php
index 97b2e046318874e14123e876fe75f38097aec5bc..1f6f0ead256395b40357fa40dd13ad3150346c17 100644
--- a/ecrire/inc/config.php
+++ b/ecrire/inc/config.php
@@ -112,7 +112,7 @@ function lire_config($cfg = '', $def = null, $unserialize = true) {
 				// ne pas essayer de deserialiser autre chose qu'une chaine
 				or !is_string($GLOBALS['meta'][$cfg])
 				// ne pas essayer de deserialiser si ce n'est visiblement pas une chaine serializee
-				or strpos($GLOBALS['meta'][$cfg], ':') === false
+				or !str_contains($GLOBALS['meta'][$cfg], ':')
 				or ($t = @unserialize($GLOBALS['meta'][$cfg])) === false) ? $GLOBALS['meta'][$cfg] : $t)
 			: $def;
 
diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php
index 3ad7544757e72d4b30e779877d067adac7f200ad..197adbd93ffd60ba09e662b424e7df7dc964f6b5 100644
--- a/ecrire/inc/filtres.php
+++ b/ecrire/inc/filtres.php
@@ -552,7 +552,7 @@ function image_filtrer($args) {
 				!$class or
 				(strpos($class, 'filtre_inactif') === false
 					// compat historique a virer en 3.2
-					and strpos($class, 'no_image_filtrer') === false)
+					and !str_contains($class, 'no_image_filtrer'))
 			) {
 				if ($reduit = $filtre($tag[3], ...$args)) {
 					// En cas de span spip_documents, modifier le style=...width:
@@ -2090,7 +2090,7 @@ function modifier_class($balise, $class, $operation = 'ajouter') {
 		$is_class_presente = false;
 		if (
 			$class_courante
-			and strpos($class_courante, (string) $c) !== false
+			and str_contains($class_courante, (string) $c)
 			and preg_match('/(^|\s)' . preg_quote($c) . '($|\s)/', $class_courante)
 		) {
 			$is_class_presente = true;
@@ -3458,7 +3458,7 @@ function http_img_pack($img, $alt, $atts = '', $title = '', $options = []) {
 		if (
 			(!isset($options['utiliser_suffixe_size'])
 				or $options['utiliser_suffixe_size'] == true
-			  or strpos($img_file, '-xx.svg') !== false)
+				or str_contains($img_file, '-xx.svg'))
 			and (preg_match(',-([0-9]+)[.](png|gif|svg)$,', $img, $regs)
 					 or preg_match(',\?([0-9]+)px$,', $img, $regs))
 		) {
diff --git a/ecrire/inc/filtres_boites.php b/ecrire/inc/filtres_boites.php
index d044f4d301483786e189d301bb13c054d5a6107d..c5deec8aa7c8d099ab967c53df44fa90ac198bfa 100644
--- a/ecrire/inc/filtres_boites.php
+++ b/ecrire/inc/filtres_boites.php
@@ -131,7 +131,7 @@ function boite_ouvrir($titre, $class = '', $head_class = '', $id = '') {
 	$class = "box $class";
 	$head_class = "box__header $head_class clearfix";
 	// dans l'espace prive, titrer en h3 si pas de balise <hn>
-	if (test_espace_prive() and strlen($titre) and strpos($titre, '<h') === false) {
+	if (test_espace_prive() and strlen($titre) and !str_contains($titre, '<h')) {
 		$titre = "<h3>$titre</h3>";
 	}
 
diff --git a/ecrire/inc/lang.php b/ecrire/inc/lang.php
index e4e21feb05bab3d2eac32b0a368e0c460ff25fb9..d8b329fff1b8bddba1b863a66e4dd243621cf27e 100644
--- a/ecrire/inc/lang.php
+++ b/ecrire/inc/lang.php
@@ -58,7 +58,7 @@ function changer_langue($lang, $liste_langues = null) {
 	if (
 		strpos($liste_langues, (string) ",$lang,") !== false
 		or ($lang = preg_replace(',_.*,', '', $lang)
-			and strpos($liste_langues, (string) ",$lang,") !== false)
+			and str_contains($liste_langues, (string) ",$lang,"))
 	) {
 		$GLOBALS['spip_lang_rtl'] = lang_dir($lang, '', '_rtl');
 		$GLOBALS['spip_lang_right'] = $GLOBALS['spip_lang_rtl'] ? 'left' : 'right';
diff --git a/ecrire/inc/pipelines.php b/ecrire/inc/pipelines.php
index 3f3364a6f410829376ec4d8573bd5ab7d1e9c045..751144204224413d5df6e3afda7a1bbdcdae2ca9 100644
--- a/ecrire/inc/pipelines.php
+++ b/ecrire/inc/pipelines.php
@@ -177,7 +177,7 @@ function f_insert_head($texte) {
 	|| ($pos = stripos($texte, '<body>'))
 	|| ($pos = 0);
 
-	if (false === strpos(substr($texte, 0, $pos), '<!-- insert_head -->')) {
+	if (!str_contains(substr($texte, 0, $pos), '<!-- insert_head -->')) {
 		$insert = "\n" . pipeline('insert_head', '<!-- f_insert_head -->') . "\n";
 		$texte = substr_replace($texte, $insert, $pos, 0);
 	}
diff --git a/ecrire/inc/plugin.php b/ecrire/inc/plugin.php
index 83edbfc9dd3283ecb71237bd52982f577075559e..983c3cff60ab9cab1d6d25902c3ecbd98ccaaa9b 100644
--- a/ecrire/inc/plugin.php
+++ b/ecrire/inc/plugin.php
@@ -864,7 +864,7 @@ function ecrire_plugin_actifs($plugin, $pipe_recherche = false, $operation = 'ra
 	$err = $msg = $header = [];
 	foreach ($plugin_valides as $p => $resume) {
 		// Les headers ne doivent pas indiquer les versions des extensions PHP, ni la version PHP
-		if (0 !== strpos($p, 'PHP:') and $p !== 'PHP') {
+		if (!str_starts_with($p, 'PHP:') and $p !== 'PHP') {
 			$header[] = $p . ($resume['version'] ? '(' . $resume['version'] . ')' : '');
 		}
 		if ($resume['dir']) {
@@ -953,7 +953,7 @@ function plugins_precompile_chemin($plugin_valides, $ordre) {
 			$prefix = strtoupper(preg_replace(',\W,', '_', $info['prefix']));
 			if (
 				$prefix !== 'SPIP'
-				and strpos($dir, ':') === false // exclure le cas des procure:
+				and !str_contains($dir, ':') // exclure le cas des procure:
 			) {
 				$contenu .= "define('_DIR_PLUGIN_$prefix',$dir);\n";
 				if (!$info['chemin']) {
@@ -1045,7 +1045,7 @@ function plugins_precompile_xxxtions($plugin_valides, $ordre) {
 				if (
 					!isset($info[$charge])
 					and $dir // exclure le cas du plugin "SPIP"
-					and strpos($dir, ':') === false // exclure le cas des procure:
+					and !str_contains($dir, ':') // exclure le cas des procure:
 					and file_exists("$dir$plug/paquet.xml") // uniquement pour les paquet.xml
 				) {
 					if (is_readable("$dir$plug/" . ($file = $info['prefix'] . '_' . $charge . '.php'))) {
diff --git a/ecrire/inc/rechercher.php b/ecrire/inc/rechercher.php
index 1f279e57a171a0d280ea49c6273d14ba30e01f41..5c3626a36065e99b2f62a91fa1c0ebba13239b18 100644
--- a/ecrire/inc/rechercher.php
+++ b/ecrire/inc/rechercher.php
@@ -85,7 +85,7 @@ function expression_recherche($recherche, $options) {
 	}
 
 	$u = $GLOBALS['meta']['pcre_u'];
-	if ($u and strpos($options['preg_flags'], (string) $u) === false) {
+	if ($u and !str_contains($options['preg_flags'], (string) $u)) {
 		$options['preg_flags'] .= $u;
 	}
 	include_spip('inc/charsets');
diff --git a/ecrire/inc/texte_mini.php b/ecrire/inc/texte_mini.php
index b030a7c54874ed03c207cc4bba071e4d81e6e8b8..ebfffc6c85f666175c5d90ef7a6937902b9d8026 100644
--- a/ecrire/inc/texte_mini.php
+++ b/ecrire/inc/texte_mini.php
@@ -240,7 +240,7 @@ function echappe_html(
 	}
 
 	if (
-		($preg or strpos($letexte, '<') !== false)
+		($preg or str_contains($letexte, '<'))
 		and preg_match_all($preg ?: _PROTEGE_BLOCS, $letexte, $matches, PREG_SET_ORDER)
 	) {
 		foreach ($matches as $regs) {
@@ -553,7 +553,7 @@ function echapper_html_suspect($texte, $options = [], $connect = null, $env = []
 	// pas de balise html ou pas d'attribut sur les balises ? c'est OK
 	if (
 		strpos($texte, '<') === false
-		or strpos($texte, '=') === false
+		or !str_contains($texte, '=')
 	) {
 		return $texte;
 	}
diff --git a/ecrire/inc/utils.php b/ecrire/inc/utils.php
index 61a400e480cdbe32e9e3acfdec98f3401e9a33a1..80f8575710fc01a87a64a127b05b2d9800460f22 100644
--- a/ecrire/inc/utils.php
+++ b/ecrire/inc/utils.php
@@ -2672,7 +2672,7 @@ function spip_initialisation_core($pi = null, $pa = null, $ti = null, $ta = null
 
 	// Sommes-nous dans l'empire du Mal ?
 	// (ou sous le signe du Pingouin, ascendant GNU ?)
-	if (isset($_SERVER['SERVER_SOFTWARE']) and strpos($_SERVER['SERVER_SOFTWARE'], '(Win') !== false) {
+	if (isset($_SERVER['SERVER_SOFTWARE']) and str_contains($_SERVER['SERVER_SOFTWARE'], '(Win')) {
 		if (!defined('_OS_SERVEUR')) {
 			define('_OS_SERVEUR', 'windows');
 		}
diff --git a/ecrire/inc/xml.php b/ecrire/inc/xml.php
index b2b0d9b9d1e98e93faddc02520ebe8d7d8b0db8f..c16c7d84662b27d61dcd30d4f288fc8867f2df9a 100644
--- a/ecrire/inc/xml.php
+++ b/ecrire/inc/xml.php
@@ -159,7 +159,7 @@ function spip_xml_parse(&$texte, $strict = true, $clean = true, $profondeur = -1
 			}
 			$content = substr($txt, 0, $p);
 			$txt = substr($txt, $p + $ncclos);
-			if ($profondeur == 0 or strpos($content, '<') === false) { // eviter une recursion si pas utile
+			if ($profondeur == 0 or !str_contains($content, '<')) { // eviter une recursion si pas utile
 			$out[$tag][] = importer_charset($content, $charset);
 			}//$content;
 			else {
diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php
index 5d3d021ae989c1b9e09b4879b78003d5fb75b8a7..45b4c1c1d6fae74db48e26df5da846dc4d2704d1 100644
--- a/ecrire/public/compiler.php
+++ b/ecrire/public/compiler.php
@@ -787,12 +787,12 @@ function calculer_dec($nom, $val) {
 	// si une variable apparait dans le calcul de la clause
 	// il faut la re-evaluer a chaque passage
 	if (
-		strpos($val, '$') !== false
+		str_contains($val, '$')
 		/*
-		OR strpos($val, 'sql_') !== false
+		OR str_contains($val, 'sql_')
 		OR (
 			$test = str_replace(array("array(",'\"',"\'"),array("","",""),$val) // supprimer les array( et les echappements de guillemets
-			AND strpos($test,"(")!==FALSE // si pas de parenthese ouvrante, pas de fonction, on peut sortir
+			AND str_contains($test,"(") // si pas de parenthese ouvrante, pas de fonction, on peut sortir
 			AND $test = preg_replace(",'[^']*',UimsS","",$test) // supprimer les chaines qui peuvent contenir des fonctions SQL qui ne genent pas
 			AND preg_match(",\w+\s*\(,UimsS",$test,$regs) // tester la presence de fonctions restantes
 		)*/
@@ -1302,7 +1302,7 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, string $conn
 
 	// rendre inertes les echappements de #[](){}<>
 	$i = 0;
-	while (false !== strpos($squelette, $inerte = '-INERTE' . $i)) {
+	while (str_contains($squelette, $inerte = '-INERTE' . $i)) {
 		$i++;
 	}
 	$squelette = preg_replace_callback(
diff --git a/ecrire/public/composer.php b/ecrire/public/composer.php
index 61ebf20095b2277d600f8256cd37cddbc83ef461..4c0e7ca827ccc21794fc065e0f54e7fb25a21ef0 100644
--- a/ecrire/public/composer.php
+++ b/ecrire/public/composer.php
@@ -306,7 +306,7 @@ function synthetiser_balise_dynamique($nom, $args, $file, $context_compil) {
 	if (
 		strncmp($file, '/', 1) !== 0
 		// pas de lien symbolique sous Windows
-		and !(stristr(PHP_OS, 'WIN') and strpos($file, ':') !== false)
+		and !(stristr(PHP_OS, 'WIN') and str_contains($file, ':'))
 	) {
 		$file = './" . _DIR_RACINE . "' . $file;
 	}
@@ -511,7 +511,7 @@ function executer_balise_dynamique($nom, $args, $context_compil) {
  * @return array|null
  */
 function chercher_balise_generique($nom) {
-	if (false === strpos($nom, '_')) {
+	if (!str_contains($nom, '_')) {
 		return null;
 	}
 	$nom_generique = $nom;
@@ -564,8 +564,8 @@ function lang_select_public($lang, $lang_select, $titre = null) {
 	elseif (
 		$lang_select !== 'oui'
 		and strlen($titre) > 10
-		and strpos($titre, '<multi>') !== false
-		and strpos(echappe_html($titre), '<multi>') !== false
+		and str_contains($titre, '<multi>')
+		and str_contains(echappe_html($titre), '<multi>')
 	) {
 		$lang = $GLOBALS['spip_lang'];
 	}
@@ -784,7 +784,7 @@ function calculer_select(
 					foreach ($join as $cle => $wj) {
 						if (
 							(is_countable($wj) ? count($wj) : 0) == 4
-							and strpos($wherestring, (string) "{$cle}.") !== false
+							and str_contains($wherestring, (string) "{$cle}.")
 						) {
 							$i = 0;
 							$wheresub[] = $wj[3];
diff --git a/ecrire/public/phraser_html.php b/ecrire/public/phraser_html.php
index cfcd8aea52d160bc4e360c578cac66927501002c..97a9ecc7136eecd674075ba9b8135f745ae7f37f 100644
--- a/ecrire/public/phraser_html.php
+++ b/ecrire/public/phraser_html.php
@@ -295,7 +295,7 @@ function phraser_args(string $texte, $fin, $sep, $result, &$pointeur_champ, &$po
 	while ($pos_debut < $length and trim($texte[$pos_debut]) === '') {
 		$pos_debut++;
 	}
-	while (($pos_debut < $length) && strpos($fin, $texte[$pos_debut]) === false) {
+	while (($pos_debut < $length) && !str_contains($fin, $texte[$pos_debut])) {
 		// phraser_arg modifie directement le $texte, on fait donc avec ici en passant par une sous chaine
 		$st = substr($texte, $pos_debut);
 		$result = phraser_arg($st, $sep, $result, $pointeur_champ);
diff --git a/ecrire/public/styliser_par_z.php b/ecrire/public/styliser_par_z.php
index 59a5f088eb36448fcd57a8614b566e2670a0a915..894757e49aa5046f23e48795d9c1d2377f5b7ab3 100644
--- a/ecrire/public/styliser_par_z.php
+++ b/ecrire/public/styliser_par_z.php
@@ -397,7 +397,7 @@ function prive_echafauder_dist($exec, $table, $table_sql, $desc_exec, $ext) {
 		$dir = reset($dir);
 		$scaffold = "<INCLURE{fond=prive/echafaudage/$dir/" . $fond . ',objet=' . $type . ',id_objet=#' . strtoupper($primary) . ',env}>';
 	} // page objets
-	elseif ($type = $desc_exec and strpos($type, '/') === false) {
+	elseif ($type = $desc_exec and !str_contains($type, '/')) {
 		$dir = z_blocs(test_espace_prive());
 		$dir = reset($dir);
 		$scaffold = "<INCLURE{fond=prive/echafaudage/$dir/objets,objet=" . $type . ',env} />';
diff --git a/ecrire/req/pg.exp.php b/ecrire/req/pg.exp.php
index 7560193c93c9a53af1184b34191f868040a65935..7357e391ac4f18a00ce931ed59c68d5df9f64ddd 100644
--- a/ecrire/req/pg.exp.php
+++ b/ecrire/req/pg.exp.php
@@ -215,7 +215,7 @@ function spip_pg_ajouter_champs_timestamp($table, $couples, $desc = '', $serveur
 		foreach ($desc['field'] as $k => $v) {
 			$v = strtolower(ltrim($v));
 			// ne pas ajouter de timestamp now() si un default est specifie
-			if (strpos($v, 'timestamp') === 0 and strpos($v, 'default') === false) {
+			if (strpos($v, 'timestamp') === 0 and !str_contains($v, 'default')) {
 				$tables[$table][] = $k;
 			}
 		}
@@ -253,8 +253,8 @@ function spip_pg_alter($query, $serveur = '', $requeter = true) {
 	$ouverte = false;
 	while ($do = array_shift($todo)) {
 		$todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . ',' . $do : $do;
-		$o = (false !== strpos($do, '('));
-		$f = (false !== strpos($do, ')'));
+		$o = (str_contains($do, '('));
+		$f = (str_contains($do, ')'));
 		if ($o and !$f) {
 			$ouverte = true;
 		} elseif ($f) {
@@ -349,7 +349,7 @@ function spip_pg_alter_add($table, $arg, $serveur = '', $requeter = true) {
 			// (colonne)
 			if ($m[1][0] == '(') {
 				$colonnes = substr($m[1], 1, -1);
-				if (false !== strpos(',', $colonnes)) {
+				if (str_contains(',', $colonnes)) {
 					spip_log('PG : Erreur, impossible de creer un index sur plusieurs colonnes'
 						. " sans qu'il ait de nom ($table, ($colonnes))", 'pg.' . _LOG_ERREUR);
 				} else {
@@ -1171,7 +1171,7 @@ function spip_pg_sequence($table, $raw = false) {
 	$prim = @$desc['key']['PRIMARY KEY'];
 	if (
 		!preg_match('/^\w+$/', $prim)
-		or strpos($desc['field'][$prim], 'int') === false
+		or !str_contains($desc['field'][$prim], 'int')
 	) {
 		return '';
 	} else {
diff --git a/ecrire/req/sqlite_generique.php b/ecrire/req/sqlite_generique.php
index be2646edbe366c78f0ce20382b834691d396283e..3e285c08fb1a327618dbe499e8fd2473c387238d 100644
--- a/ecrire/req/sqlite_generique.php
+++ b/ecrire/req/sqlite_generique.php
@@ -63,7 +63,7 @@ function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $
 
 	// determiner le dossier de la base : $addr ou _DIR_DB
 	$f = _DIR_DB;
-	if ($addr and strpos($addr, '/') !== false) {
+	if ($addr and str_contains($addr, '/')) {
 		$f = rtrim($addr, '/') . '/';
 	}
 
@@ -206,8 +206,8 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true) {
 	$ouverte = false;
 	while ($do = array_shift($todo)) {
 		$todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . ',' . $do : $do;
-		$o = (false !== strpos($do, '('));
-		$f = (false !== strpos($do, ')'));
+		$o = (str_contains($do, '('));
+		$f = (str_contains($do, ')'));
 		if ($o and !$f) {
 			$ouverte = true;
 		} elseif ($f) {
@@ -371,7 +371,7 @@ function spip_sqlite_alter($query, $serveur = '', $requeter = true) {
 					// (colonne)
 					if ($colonne_origine[0] == '(') {
 						$colonnes = substr($colonne_origine, 1, -1);
-						if (false !== strpos(',', $colonnes)) {
+						if (str_contains(',', $colonnes)) {
 							spip_log('SQLite : Erreur, impossible de creer un index sur plusieurs colonnes'
 								. " sans qu'il ait de nom ($table, ($colonnes))", 'sqlite.' . _LOG_ERREUR);
 							break;
@@ -951,7 +951,7 @@ function spip_sqlite_fetch($r, $t = '', $serveur = '', $requeter = true) {
 	// Renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
 	// suppression de 'table.' pour toutes les cles (c'est un peu violent !)
 	// c'est couteux : on ne verifie que la premiere ligne pour voir si on le fait ou non
-	if (strpos(implode('', array_keys($retour)), '.') !== false) {
+	if (str_contains(implode('', array_keys($retour)), '.')) {
 		foreach ($retour as $cle => $val) {
 			if (($pos = strpos($cle, '.')) !== false) {
 				$retour[substr($cle, $pos + 1)] = &$retour[$cle];
@@ -1815,7 +1815,7 @@ function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true) {
 				// rustine pour DECIMAL(10,2)
 				// s'il y a une parenthèse fermante dans la clé
 				// ou dans la définition sans qu'il n'y ait une ouverture avant
-				if (false !== strpos($k, ')') or preg_match('/^[^\(]*\)/', $def)) {
+				if (str_contains($k, ')') or preg_match('/^[^\(]*\)/', $def)) {
 					$fields[$k_precedent] .= ',' . $k . ' ' . $def;
 					continue;
 				}
diff --git a/ecrire/xml/analyser_dtd.php b/ecrire/xml/analyser_dtd.php
index e3672034e24da0192228a434d4c2ab3b64be2ed1..07e137d9336c75e634009220bfd3c1c5144a5c6f 100644
--- a/ecrire/xml/analyser_dtd.php
+++ b/ecrire/xml/analyser_dtd.php
@@ -340,7 +340,7 @@ function analyser_dtd_element($dtd, &$dtc, $grammaire) {
 		$last = substr($val, -1);
 		if (
 			preg_match('/ \w/', $val)
-			or (!empty($last) and strpos('*+?', $last) === false)
+			or (!empty($last) and !str_contains('*+?', $last))
 		) {
 			$dtc->regles[$nom] = "/^$val$/";
 		} else {
diff --git a/ecrire/xml/sax.php b/ecrire/xml/sax.php
index 8537bbfd011b76078d56d8f734e10fac6decd973..4b45a84892ed3b44a23d2099adab40450cdeba5a 100644
--- a/ecrire/xml/sax.php
+++ b/ecrire/xml/sax.php
@@ -55,7 +55,7 @@ function xml_debutElement($phraseur, $name, $attrs) {
 	$att = '';
 	$sep = ' ';
 	foreach ($attrs as $k => $v) {
-		$delim = strpos($v, "'") === false ? "'" : '"';
+		$delim = !str_contains($v, "'") ? "'" : '"';
 		$val = xml_entites_html($v);
 		$att .= $sep . $k . '=' . $delim
 			. ($delim !== '"' ? str_replace('&quot;', '"', $val) : $val)