WP Manifestindependent plugin directory
manifest / utilities / french-schools-map

French Schools Map WP Registry grade B. Medium-severity findings · 1 findingWP RegistryMedium-severity findings · 1 findingOpen the reportB

Carte interactive des établissements scolaires français basée sur OpenStreetMap et les données open data du Ministère de l'Éducation Nationale.

★ 0stars
64release downloads
≈10active sites
v1.5.2latest · 1mo ago

Install

Download french-schools-map.zip From the v1.5.2 release on GitHub, Sep 2, 2026

Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/guilamu/french-schools-map/releases/download/v1.5.2/french-schools-map.zip
Updates itself. It ships its own updater, so new versions appear under Dashboard → Updates.

Carte interactive des établissements scolaires français, alimentée par les données open data du Ministère de l'Éducation Nationale.

Description

Ce plugin affiche une carte interactive des ~69 000 établissements scolaires français (écoles, collèges, lycées) directement dans vos pages ou articles WordPress. Les données proviennent de l'Annuaire de l'Éducation Nationale et sont synchronisées automatiquement chaque mois.

Fonctionnalités

  • 🗺️ Carte interactive OpenStreetMap avec Leaflet.js (aucune clé API requise)
  • 📍 ~69 000 établissements géolocalisés sur la carte
  • 🔍 Filtres dynamiques : type (école/collège/lycée), statut (public/privé), département, éducation prioritaire
  • 🔎 Recherche textuelle par nom d'établissement ou ville
  • 📊 Clustering intelligent pour des performances optimales (Leaflet.markercluster)
  • 🎨 Marqueurs colorés par type d'établissement
  • 📱 Responsive : adapté mobile et desktop
  • 🌐 Académies & Départements : filtres géographiques avec zoom automatique sur la zone sélectionnée
  • 📋 Popup détaillée : nom, adresse, téléphone, email, statut REP/REP+, itinéraire (chargement automatique pour < 1 500 établissements)
  • 📦 Shortcode et bloc Gutenberg disponibles
  • 🔄 Synchronisation mensuelle automatique via WP-Cron
  • 📍 Géolocalisation : bouton "Me localiser"

Key Features

  • Open Data: Données officielles du Ministère de l'Éducation Nationale (~69 000 établissements)
  • No API Key: OpenStreetMap/Leaflet.js par défaut — aucune clé API requise (une clé CARTO gratuite est possible en option)
  • Multilingual: Fonctionne avec tout contenu linguistique
  • Translation-Ready: Toutes les chaînes sont internationalisées
  • Secure: Requêtes REST authentifiées par nonce WordPress, données sanitisées
  • GitHub Updates: Mises à jour automatiques depuis les releases GitHub

Requirements

  • WordPress 5.8 or higher
  • PHP 7.4 or higher

Installation

  1. Téléchargez le dossier french-schools-map
  2. Uploadez-le dans /wp-content/plugins/
  3. Activez le plugin via le menu Extensions
  4. Rendez-vous dans Réglages → French Schools Map pour lancer la première synchronisation
  5. Ajoutez le shortcode [french_schools_map] dans une page ou utilisez le bloc Gutenberg

FAQ

Aucune école ne s'affiche sur la carte ?

Vérifiez que la synchronisation a bien été effectuée : allez dans Réglages → French Schools Map et cliquez sur "Synchroniser maintenant". La première synchronisation peut prendre quelques minutes.

Le plugin nécessite-t-il une clé API ?

Non par défaut : tuiles OpenStreetMap et API Open Data, toutes deux gratuites et sans clé. Une clé CARTO (gratuite, sur https://carto.com/basemaps/apikey/) n'est requise que pour les fonds Voyager, Positron ou Dark Matter, qui affichent sinon un filigrane « API KEY REQUIRED ».

departement et academie sont-ils cumulables ?

Non. Si les deux sont renseignés, departement est prioritaire. La valeur configurée dans les réglages globaux prend également le dessus sur les attributs du bloc Gutenberg pour éviter des affichages incohérents.

Puis-je personnaliser les marqueurs ?

Oui, utilisez le filtre fsm_marker_color :

add_filter( 'fsm_marker_color', function( $color, $type ) {
    return $color;
}, 10, 2 );

Les données sont-elles à jour ?

Les données sont synchronisées automatiquement chaque mois depuis l'Annuaire de l'Éducation Nationale. Vous pouvez aussi forcer une synchronisation manuelle depuis la page de réglages.

Project Structure

.
├── french-schools-map.php             # Main plugin file (shortcode, block, basemap resolution)
├── uninstall.php                      # Cleanup on uninstall
├── README.md
├── assets
│   ├── css
│   │   ├── fsm-admin.css              # Admin settings page styles
│   │   └── fsm-map.css                # Frontend map styles
│   └── js
│       ├── fsm-admin.js               # Admin settings page script
│       ├── fsm-block.js               # Gutenberg block editor script
│       └── fsm-map.js                 # Frontend map logic (Leaflet)
├── includes
│   ├── class-fsm-academies.php        # Académies data & département mapping
│   ├── class-fsm-admin.php            # Admin settings page
│   ├── class-fsm-local-db.php         # Local DB sync & REST helpers
│   ├── class-fsm-rest-api.php         # REST API endpoints
│   ├── class-github-updater.php       # GitHub auto-updates
│   └── Parsedown.php                  # Markdown parser for the "View details" popup
└── languages
    ├── french-schools-map-fr_FR.mo    # French translation (binary)
    ├── french-schools-map-fr_FR.po    # French translation (source)
    └── french-schools-map.pot         # Translation template

Utilisation

Shortcode

[french_schools_map]

Attributs disponibles

Attribut Défaut Description
height 600px Hauteur de la carte
center_lat 46.603354 Latitude du centre initial
center_lng 1.888334 Longitude du centre initial
zoom 6 Niveau de zoom initial (1-18)
types all Types à afficher : Ecole, Collège, Lycée (séparés par des virgules)
departement all Filtrer par département
academie all Filtrer par académie (ex: Lyon, Versailles)
statut all Public, Privé ou all
education_prioritaire all REP, REP+ ou all
show_filters true Afficher le panneau de filtres
show_search true Afficher la barre de recherche
show_filter_academie true Afficher le filtre Académie
show_filter_dept true Afficher le filtre Département
show_filter_statut true Afficher le filtre Statut (Public/Privé)
show_filter_types true Afficher le filtre Types (École/Collège/Lycée)
show_filter_ep true Afficher le filtre Éducation prioritaire
show_circo_zones true Afficher les zones colorées par circonscription IEN
cluster true Activer le clustering des marqueurs
max_zoom 18 Zoom maximal
tile_url (vide) URL personnalisée pour les tuiles cartographiques (prioritaire sur le fond de carte des réglages)

Note : departement et academie sont mutuellement exclusifs. Si les deux sont renseignés, departement est prioritaire.

Exemples

Carte des collèges publics de Paris :

[french_schools_map types="Collège" statut="Public" departement="Paris" zoom="12" center_lat="48.8566" center_lng="2.3522"]

Carte des lycées sans filtres :

[french_schools_map types="Lycée" show_filters="false" height="400px"]

Carte de l'académie de Lyon :

[french_schools_map academie="Lyon" zoom="8" center_lat="45.764" center_lng="4.8357"]

Carte d'un département avec zones de circonscription :

[french_schools_map departement="Haute-Garonne" show_circo_zones="true"]

Réglages par défaut

Dans Réglages → French Schools Map, vous pouvez définir un département ou une académie par défaut. Ces valeurs seront utilisées automatiquement si le shortcode ne précise rien.

Fond de carte

Toujours dans Réglages → French Schools Map, section Fond de carte :

Réglage Rôle
Clé API CARTO Laissée vide, la carte utilise OpenStreetMap. Renseignée, elle active les fonds CARTO. Obtenir une clé gratuite
Style CARTO Voyager, Positron (gris clair) ou Dark Matter, avec ou sans libellés. Utilisé uniquement si une clé est renseignée

Ordre de priorité du fond de carte : attribut tile_url du shortcode > CARTO (si une clé est enregistrée) > OpenStreetMap.

La clé est transmise au navigateur des visiteurs à chaque requête de tuile, comme toute clé de fond de carte côté client : restreignez-la à votre domaine depuis votre compte CARTO.

Bloc Gutenberg

Le bloc French Schools Map est disponible dans l'éditeur. Les mêmes paramètres sont configurables via l'inspecteur de bloc.

Source de données

Les données proviennent du portail Open Data du Ministère de l'Éducation Nationale :

  • Dataset : Annuaire de l'éducation
  • API : OpenDataSoft API v2.1
  • Fréquence : Synchronisation mensuelle automatique
  • Contours communaux : geo.api.gouv.fr (pour les zones colorées par circonscription)

Données affichées

Champ Description
Nom Nom de l'établissement
Type École, Collège, Lycée
Nature Maternelle, Élémentaire, etc.
Statut Public / Privé
Adresse Adresse postale complète
Téléphone Numéro de contact
Email Adresse email
Éducation prioritaire REP, REP+ ou non
Circonscription Circonscription IEN (1er degré)

Administration

La page Réglages → French Schools Map permet de :

  • Voir le statut de la synchronisation (dernière date, nombre d'enregistrements)
  • Lancer une synchronisation manuelle
  • Définir le département ou l'académie affichés par défaut

API REST

Le plugin expose des endpoints REST pour les développeurs :

Endpoint Description
GET /wp-json/fsm/v1/markers Tous les marqueurs (format compact)
GET /wp-json/fsm/v1/schools Détails complets (utilisé auto. quand < 1 500 résultats)
GET /wp-json/fsm/v1/school/{id} Détails d'un établissement
GET /wp-json/fsm/v1/departments Liste des départements
GET /wp-json/fsm/v1/academies Carte académies → départements
GET /wp-json/fsm/v1/circonscriptions Circonscriptions d'un département
GET /wp-json/fsm/v1/commune-circo-map Mapping commune → circonscription
GET /wp-json/fsm/v1/stats Statistiques globales

Paramètres de filtrage (endpoint markers)

  • types : Type d'établissement (ex: Ecole,Collège)
  • departement : Nom du département
  • statut : Public ou Privé
  • ep : REP ou REP+
  • search : Recherche textuelle

Performance

Le plugin gère ~69 000 points grâce à :

  • Base de données locale : les données sont stockées dans une table WordPress dédiée
  • Clustering : Leaflet.markercluster regroupe les marqueurs proches
  • Cache : les réponses API sont mises en cache (transients WordPress + headers HTTP)
  • Format compact : les marqueurs sont transmis en tableaux d'arrays (pas d'objets JSON verbeux)
  • Chargement asynchrone : les détails ne sont récupérés qu'au clic sur un marqueur

Known Issues

  • La synchronisation initiale peut prendre plusieurs minutes selon les performances du serveur (téléchargement de ~69 000 enregistrements).
  • Sur les hébergements mutualisés avec un max_execution_time très court, la synchronisation peut échouer et nécessiter plusieurs tentatives.
  • Les zones de circonscription pour les communes sans école sont approximées par la circonscription la plus proche géographiquement.

Changelog

1.5.2 - 2026-09-02

  • Fixed: Le popup « Voir les détails » affichait un lien « WordPress.org Plugin Page » pointant vers une page inexistante, le plugin n'étant distribué que sur GitHub. WordPress fabrique ce lien à partir du slug tant que la réponse plugins_api ne se déclare pas external ; elle le fait désormais
  • Fixed: Le plugin annonçait deux versions de WordPress testées différentes selon le chemin de lecture — 6.7 dans le transient de mise à jour, la version du site elle-même dans le popup. Les deux utilisent maintenant la même constante, portée à 7.1 ; la seconde valeur revenait à se déclarer compatible avec n'importe quelle version, ce qui faisait signaler le plugin comme non maintenu
  • Fixed: Dans l'onglet Changelog, l'entrée d'une version non encore installée s'affichait en police plus petite et sans date, car elle était construite séparément du reste du changelog. Elle suit désormais le même format « version - date » que les entrées issues du README
  • New: Les versions non installées apparaissent dans un bloc distinct avec un badge, et la version installée est signalée par un badge « Installed »
  • New: Toutes les releases plus récentes que la version installée sont listées dans le changelog, et non plus seulement la dernière : un site en retard de plusieurs versions ne saute plus les entrées intermédiaires
  • Improved: Le corps des releases GitHub est normalisé avant affichage — titre de version en double retiré, lien « Full Changelog » raccourci, niveaux de titres alignés sur ceux du README
  • Improved: Une release déjà documentée dans le README n'est plus affichée deux fois
  • Improved: Les transients du système de mise à jour sont supprimés à la désinstallation du plugin

1.5.1 - 2026-09-01

  • Fixed: Filtre par circonscription et recherche renvoyaient « Erreur de chargement. » sur les sites protégés par un pare-feu applicatif (BulletProof Security, Wordfence, mod_security) : ces WAF renvoient un 403 dès qu'une apostrophe apparaît dans la query string, ce que déclenchent les noms français (« Circonscription d'inspection du 1er degré d'Auterive », commune « L'Union », département « Côte-d'Or »). La query string concernée est désormais transmise encodée en base64url et décodée côté serveur avant validation
  • Fixed: Alignement du titre « Fond de carte » sur la colonne des libellés dans la page de réglages

1.5.0 - 2026-08-31

  • Fixed: Le fond de carte par défaut passe de CARTO (cartocdn.com) aux tuiles standard OpenStreetMap. CARTO refuse désormais les requêtes anonymes et affichait un filigrane « API KEY REQUIRED » sur toute la carte
  • New: Prise en charge des fonds de carte CARTO via une clé API, avec un réglage Fond de carte (clé + choix du style Voyager / Positron / Dark Matter) et un lien direct vers https://carto.com/basemaps/apikey/
  • Improved: L'attribution du fond de carte est désormais construite côté serveur et suit le fournisseur réellement utilisé

1.4.0 - 2026-04-17

  • Fixed: Erreur « Duplicate entry » lors de la synchronisation mensuelle — les identifiants en double dans le CSV source (ex. 9840265R en Polynésie Française) sont désormais gérés via ON DUPLICATE KEY UPDATE
  • Improved: Le popup « Voir les détails » affiche désormais un bandeau géométrique CSS (sans image externe) et prépend le changelog de la release GitHub lorsqu'une mise à jour est disponible
  • Improved: Ajout d'un log au démarrage de la synchronisation pour faciliter le débogage

1.3.8 - 2026-03-30

  • Improved: Réécriture du système de mise à jour GitHub : popup "Voir les détails" avec onglets Description, Installation, FAQ et Changelog parsés depuis le README.md local (via Parsedown)
  • New: Lien "Voir les détails" (thickbox) dans la liste des extensions
  • New: Conversion des tableaux Markdown en structures div/span compatibles wp_kses
  • New: Injection CSS via admin_head pour le style de la modale d'informations du plugin

1.3.7 - 2026-03-09

  • Improved: Ajout du préfixe "Circonscription de " dans l'infobulle au survol des zones de circonscription sur la carte

1.3.6 - 2026-03-09

  • Fixed: Correction d'une PHP Notice : suppression de l'appel de traduction dans le filtre cron_schedules pour éviter que _load_textdomain_just_in_time ne soit déclenché avant init.

1.3.5 - 2026-03-04

  • Fixed: les attributs statut, types et education_prioritaire du shortcode sont désormais pris en compte (pré-sélection des filtres HTML côté serveur)
  • Fixed: normalisation des noms de types dans le shortcode (ex. Écoles → Ecole, Collèges → Collège, Lycées → Lycée)
  • Fixed: les valeurs statut, types et education_prioritaire de la configuration sont envoyées au REST API même lorsque les widgets de filtre sont masqués
  • New: constructeur de shortcode interactif sur la page de réglages (génération et copie du shortcode en temps réel)

1.3.0 - 2026-03-04

  • Transports en commun (Île-de-France) : calque optionnel affichant les lignes de métro, RER, tramway et train ainsi que les gares/stations
    • Données officielles Île-de-France Mobilités (API Explore v2, Licence Ouverte)
    • Lignes colorées avec les couleurs officielles de chaque ligne
    • Stations affichées en cercles avec tooltip au survol (nom + lignes desservies, ex. « RER E »)
    • Bouton 🚇 dans la barre d'outils pour activer/désactiver
    • Attribut show_transport (défaut false) dans le shortcode et le bloc Gutenberg

1.2.0 - 2026-03-04

  • Zones de circonscription IEN : fond de couleur par circonscription affiché lorsqu'un département est sélectionné
    • Contours communaux via l'API geo.api.gouv.fr, colorés par circonscription
    • Tooltip au survol avec le nom de la circonscription
    • Les communes sans école sont assignées à la circonscription la plus proche
    • Attribut show_circo_zones (défaut true) pour activer/désactiver
  • Nouvel endpoint REST GET /fsm/v1/commune-circo-map?departement=...
  • Ajout de code_commune dans le schéma de la base de données
  • Correction du schéma DB lors de la synchronisation (appel dbDelta avant import)
  • Correction du cron : la prochaine synchronisation s'affiche correctement (1 mois après le dernier sync)
  • Correction i18n : toutes les chaînes admin utilisent désormais des msgids anglais conformes au fichier .pot

1.1.3 - 2026-03-03

  • Ajout d'une infobulle (tooltip) au survol de chaque marqueur : affiche le nom court de l'établissement (sans le préfixe de type : École, Collège, Lycée…) suivi du nom de la ville

1.1.2 - 2026-03-02

  • Ajout de la circonscription par défaut dans le bloc Gutenberg (s'affiche uniquement si un département est sélectionné)

1.1.1 - 2026-03-02

  • Affichage du nom de la circonscription (nettoyé) dans la popup de détail de chaque école

1.1.0 - 2026-03-02

  • Ajout du filtre « Circonscription » : un menu déroulant apparaît automatiquement lorsqu'un département est sélectionné
  • Nettoyage automatique des noms de circonscriptions (suppression des préfixes « Circonscription d'inspection du 1er degré de/du/d' », etc.)
  • Nouvel endpoint REST GET /fsm/v1/circonscriptions?departement=...
  • Le paramètre circonscription est pris en charge par les endpoints /markers et /schools

1.0.0

  • Initial release
  • Carte interactive avec Leaflet.js et OpenStreetMap
  • Filtres : type, statut, département, académie, éducation prioritaire
  • Recherche textuelle par nom ou ville
  • Clustering intelligent (Leaflet.markercluster)
  • Synchronisation mensuelle automatique via WP-Cron
  • Endpoints REST API
  • Bloc Gutenberg et shortcode
  • Géolocalisation (bouton "Me localiser")
  • Mises à jour automatiques depuis GitHub

Acknowledgements

Security

If you discover a security vulnerability in this plugin, please report it responsibly through GitHub Security Advisories. Do not open a public issue for security reports.

Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

For translations, the plugin uses WordPress i18n. You can contribute translations by editing the .po files in the languages/ directory and generating the corresponding .mo files with the wp i18n CLI commands.

License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) - see the LICENSE file for details.


Made with love for the WordPress community

Releases

15 releases. Each count is every asset in that release; expand a row for the breakdown.

Tag
Published
Assets
Downloads
v1.5.2 latest
Sep 2, 2026 1mo ago
french-schools-map.zip
10
Sep 1, 2026 1mo ago
french-schools-map.zip
7
Aug 31, 2026 1mo ago
french-schools-map.zip
9
Apr 17, 2026 6mo ago
french-schools-map.zip
9
Mar 30, 2026 6mo ago
french-schools-map.zip
6
Mar 9, 2026 7mo ago
french-schools-map.zip
3
Mar 9, 2026 7mo ago
french-schools-map.zip
5
Mar 4, 2026 7mo ago
french-schools-map.zip
1
Mar 4, 2026 7mo ago
french-schools-map.zip
0
Mar 4, 2026 7mo ago
french-schools-map.zip
1
Mar 3, 2026 7mo ago
french-schools-map.zip
2
Mar 2, 2026 7mo ago
french-schools-map.zip
3
Mar 2, 2026 7mo ago
french-schools-map.zip
1
Mar 2, 2026 7mo ago
french-schools-map.zip
3
Mar 1, 2026 7mo ago
french-schools-map.zip
4

Active-site estimate ≈10 comes from the median of recent superseded releases. Method.

B grade

Security

French Schools Map 1.5.2 · audited by WP Registry

Medium-severity findings.

1 medium
Audited release
1.5.2
Findings
1
Worst severity
medium
Content hash
1522c473307d04c66eeeba7d…

Findings

  • medium Unauthenticated REST cache keys let visitors flood wp_options with full school dumps

    dos

    GET /fsm/v1/markers and GET /fsm/v1/schools are registered with permission_callback __return_true. Both hash the raw filter object (types, departement, academie, statut, ep, search, circonscription) into a transient key and, when the query returns any rows, store the entire result for one hour. get_schools() is SELECT * with no LIMIT even though the callback comment says the client should only call it for <1500 rows; get_markers() can similarly cache the full ~69k-row compact list. An unauthenticated visitor can keep the result non-empty while varying a dummy IN() extra (e.g. types=Ecole,<random>) or any matching search string, producing a new multi-megabyte _transient_fsm_schools_* / _transient_fsm_markers_* option on every request. clear_marker_caches() after sync deletes fsm_markers_* but never fsm_schools_*. This is not content injection (cached rows come from the local table) but it is an unauthenticated site-wide state write that can grow wp_options without bound for the TTL window and is cheap to repeat.

    includes/class-fsm-rest-api.php:247-302

    Recommendation

    Do not cache REST results under unbounded attacker-controlled keys. Use a small allowlist of filter values (known types/départements) or a fixed-size LRU/object-cache bucket; ignore unknown types tokens; cap search cache keys (or do not cache search at all). Enforce a server-side LIMIT on /schools (matching the documented 1500) and reject or ignore extra comma-separated type values that are not in {Ecole,Collège,Lycée}. Have clear_marker_caches() also delete _transient_fsm_schools_*.

WP Registry hashes the installable build and reports on that exact bytes-for-bytes copy. Embargoed findings are withheld until they are disclosed, so a clean verdict means nothing public is outstanding. WP Manifest does not audit code itself.