import db from ..flow.ensure_flow_schema import ensure_flow_schema def _collect_ids(conn, screen_id, root_id): """Rassemble l'id de cet élément et de TOUS ses descendants — ceux qu'une suppression en cascade (parent_id ON DELETE CASCADE, voir ensure_schema.py) va de toute façon supprimer automatiquement en même temps, sans passer par ce fichier. Nécessaire pour nettoyer AUSSI les références de la Logique de la scène vers un simple DESCENDANT, pas seulement vers l'élément explicitement supprimé.""" rows = conn.execute( "SELECT id, parent_id FROM _screen_elements WHERE screen_id = ?", (screen_id,) ).fetchall() children_of = {} for r in rows: if r["parent_id"]: children_of.setdefault(r["parent_id"], []).append(r["id"]) ids = [root_id] stack = [root_id] while stack: current = stack.pop() for child_id in children_of.get(current, []): ids.append(child_id) stack.append(child_id) return ids def delete_element(slug, element_id): ensure_flow_schema(slug) conn = db.connect(slug) row = conn.execute("SELECT screen_id FROM _screen_elements WHERE id = ?", (element_id,)).fetchone() if not row: conn.close() return ids = _collect_ids(conn, row["screen_id"], element_id) placeholders = ",".join("?" * len(ids)) # Un nœud de la Logique de la scène (déclencheur "clic sur cet # élément"/action "Modifier cet élément"...) ou une ancienne action du # système _actions (conservé pour compatibilité) qui référence # l'élément supprimé OU L'UN DE SES DESCENDANTS n'a plus aucun sens une # fois l'élément disparu — et ces colonnes (trigger_element_id/ # target_element_id) n'ont volontairement PAS de ON DELETE CASCADE (un # élément ne doit pas pouvoir être supprimé "par erreur" en cascade # depuis un nœud de logique qu'on modifie). Sans ce nettoyage préalable, # PRAGMA foreign_keys=ON (voir db/connection.py) fait échouer la # suppression elle-même avec "FOREIGN KEY constraint failed". conn.execute( f"DELETE FROM _flow_nodes WHERE trigger_element_id IN ({placeholders}) OR target_element_id IN ({placeholders})", ids + ids, ) conn.execute(f"DELETE FROM _actions WHERE target_element_id IN ({placeholders})", ids) conn.execute("DELETE FROM _screen_elements WHERE id = ?", (element_id,)) conn.commit() conn.close()