Skip to content

Scripts bin/

Point d’entrée en ligne de commande de Hydrogen. Trois familles :

  • Crons / workers — à planifier (Task Scheduler en local, cron en prod). Ils vidangent des tampons, recalculent des agrégats ou régénèrent des fichiers statiques.
  • Opérations ponctuelles — déploiement, bundling des migrations, application des réglages Meilisearch. Lancés à la main au moment voulu.
  • Outils de dev / debug — harnais de test et diagnostic, jamais en prod.

Invocation PHP. Le binaire n’est pas dans le PATH sur la machine de dev : utiliser le chemin complet, p. ex. /c/laragon/bin/php/php-8.4.4-nts-Win32-vs17-x64/php.exe bin/<script>.php. Sur le serveur, php bin/<script>.php suffit.

Tous les scripts chargent .env via Hydrogen\Config\Env::load() puis construisent le conteneur PHP-DI (useAutowiring(true) + useAttributes(true)), sauf robots-generate.php (pas besoin du conteneur).

Convention de codes de sortie : 0 succès · 1 échec de bootstrap / IO · 2 échec d’exécution (worker à relancer) ou arguments invalides.


À cadencer périodiquement. Sauf mention contraire, un seul worker suffit : les tampons sont vidangés FIFO par id auto-incrémenté et chaque lot est commité atomiquement, donc deux workers concurrents ne feraient que se disputer les mêmes lignes (le perdant noop).

Seul script Python de bin/. Worker hors-bande de description IA : il draine la file work.media_to_describe sans passer par l’endpoint synchrone /describe-ai (qui timeoute sur les modèles lents). Par média : récupère la vignette JPEG (GET /admin/media/{hex}/base64?format=jpg), appelle le modèle vision directement (/v1/chat/completions), puis persiste via POST /admin/media/describe (cœur) + POST /admin/media/{hex}/enrichment (poi/person_count), et retire la ligne de file.

Terminal window
# dépendances (une fois) : py -m pip install PyMySQL requests
py -3 bin/describe_worker.py --env C:\chemin\.env --log C:\chemin\worker.log
py -3 bin/describe_worker.py --dry-run --batch 1 # test à blanc
  • Cadence : toutes les minutes — un verrou OS (fcntl/msvcrt) fait sortir une exécution si une précédente tourne encore, et se relâche même en cas de crash.
  • Multi-environnement : la file work est partagée (dev/preprod/prod). Chaque ligne est estampillée environment à l’enqueue depuis WORK_QUEUE_ENV ; le worker ne claim que sa propre valeur. WORK_QUEUE_ENV + APP_URL + ADMIN_API_TOKEN doivent viser le même environnement.
  • Options : --env <fichier>, --batch <n>, --dry-run, --log <fichier> (auto-log + rotation DESCRIBE_WORKER_LOG_MAX_BYTES), --verbose.
  • File : la ligne est retirée sur succès et sur échec spécifique au média (4xx, image rejetée, JSON illisible) ; gardée sur échec transitoire d’infra (connexion / timeout / 5xx) pour re-tentative.
  • Modèle : éviter un modèle « raisonnant » (thinking) — il épuise le budget tokens et renvoie content vide ; rester sur un modèle rapide non-raisonnant.

Pousse les notifications en file vers OneSignal (1 ligne → 1 push, N lignes → un digest par destinataire).

Terminal window
php bin/notifications-flush.php
  • Cadence : NOTIFICATION_DIGEST_INTERVAL_MINUTES (2 en dev, 5 en prod).
  • Sortie : recipients, pushed, skipped, failed.
  • Service : NotificationFlushService.

Vidange le tampon de compteurs média, met à jour media_stats + media_view_daily, puis GC la table de déduplication.

Terminal window
php bin/media-counters-flush.php
  • Cadence : MEDIA_COUNTERS_FLUSH_TICK_SECONDS (défaut 30 s en prod).
  • Sortie : drained, bumped, deletedEvents, gcRows.
  • Service : MediaCountersFlushService.

Identique au précédent pour les profils utilisateur : user_stats + user_view_daily.

Terminal window
php bin/user-counters-flush.php
  • Cadence : USER_COUNTERS_FLUSH_TICK_SECONDS (défaut 30 s en prod).
  • Sortie : drained, bumped, deletedEvents, gcRows.
  • Service : UserCountersFlushService.

Vidange le tampon de clics (tracking_event) et met à jour tracking_stats + tracking_daily. Les conversions ne passent pas par ici (écrites en synchrone par l’endpoint postback admin).

Terminal window
php bin/tracking-flush.php
  • Cadence : TRACKING_FLUSH_TICK_SECONDS (défaut 30 s en prod).
  • Sortie : drained, bumped, deletedEvents.
  • Service : TrackingFlushService.

Efface irréversiblement les comptes dont la fenêtre de grâce RGPD est écoulée : suppression des médias possédés (fichiers + DB + index), anonymisation de la ligne user, retrait du document de recherche et du token de suppression.

Terminal window
php bin/account-purge.php [limit]
  • Argument : limit plafonne le nombre de comptes traités ce tick (défaut ACCOUNT_PURGE_BATCH_SIZE, fallback 50).
  • Cadence : quotidienne. Idempotent — un crash retente au tick suivant.
  • Sortie : purgedUsers, erasedMedias.
  • Service : AccountPurgeService.

Recalcule le rollup KPI quotidien (hxa_bo.platform_metric_daily) lu par les dashboards de tendances du back-office.

Terminal window
php bin/platform-metrics-rollup.php
  • Cadence : une fois par jour, hors pointe (p. ex. 03:00). La fenêtre PLATFORM_METRICS_LOOKBACK_DAYS (défaut 7) re-plie les derniers jours pour corriger les lignes arrivées en retard. UPSERT → rattrapage manuel sûr.
  • Sortie : days, flowRows, snapshotRows, countryRows.
  • Service : PlatformMetricsRollupService.

Régénère public/sitemap.xml à partir des providers de sitemap enregistrés. Écriture atomique (.tmp + rename()) pour qu’un crawler ne voie jamais un document à moitié écrit.

Terminal window
php bin/sitemap-generate.php
  • Cadence : périodique, pour rester en phase avec le catalogue (nouveaux pays indexés, nouvelles pages du registry…).
  • Sortie : nombre d’URLs, octets, durée.
  • Fichier statique : servi directement par le serveur web, hors hot path PHP.

Régénère public/robots.txt à partir de APP_URL. Même écriture atomique.

Terminal window
php bin/robots-generate.php
  • Cadence : à chaque changement de APP_URL (typiquement au déploiement) ou dans le même tick que sitemap-generate.php.
  • Prérequis : APP_URL non vide (sinon code 1).
  • Sortie : Disallow: /api/ + /admin/, ligne Sitemap: vers sitemap.xml.

Déploiement FTP/FTPS à la demande, push du delta uniquement (cf. docs/deploy.md pour la configuration et les détails).

Terminal window
php bin/deploy.php [--config=PATH] [--dry-run] [--mirror] [--help]
php bin/deploy.php --rollback [--backup=ID] [--dry-run] [--config=PATH]
OptionEffet
--config=PATHChemin du fichier de config (défaut ./deploy.config.php).
--dry-runAffiche le plan sans contacter le serveur.
--mirrorSupprime aussi les fichiers distants absents en local.
--rollbackAnnule le dernier déploiement depuis sa sauvegarde.
--backup=IDSauvegarde précise à restaurer (défaut : la plus récente).
--helpAffiche l’aide.
  • Codes : 0 ok / dry-run · 1 config ou transfert · 2 arguments invalides.

Regroupe les migrations SQL non encore déployées en un fichier par base (database/deploy/<clé>.sql), à exécuter sur le serveur puis supprimer. Pas de runner automatique : le schéma est appliqué à la main.

Terminal window
php bin/migrations-bundle.php # génère les bundles (sûr, relançable)
php bin/migrations-bundle.php --dry-run # liste le delta sans écrire
php bin/migrations-bundle.php --mark # avance le watermark (APRÈS un déploiement réussi)
  • Delta = migrations dont le préfixe YYYY_MM_DD_HHMMSS est supérieur au watermark de database/migrations/.bundle-state.json.
  • Base cible = directive d’en-tête -- @database: <clé> sur sa propre ligne. Clés : main (défaut → DB_NAME), bo (BO_DB_NAME), work (WORK_DB_NAME). Le fichier généré n’émet pas de USE : l’opérateur choisit la base à l’exécution.
  • Flux : générer → exécuter les .sql--mark → supprimer database/deploy/.
  • Codes : 0 ok · 1 IO · 2 arguments invalides.

Pousse les réglages d’index média + synonymes dont dépend le pipeline hashtags. Idempotent (updateSettings / updateSynonyms sont des upserts côté serveur).

Terminal window
php bin/media-meili-apply-settings.php

À lancer :

  • après le premier déploiement (l’index refuse les filtres hashtags= et les facetSearch tant que filterableAttributes ne liste pas hashtags),

  • après édition de config/hashtag_synonyms.php (Meili remplace la map en entier),

  • après modification de la forme des réglages dans MeilisearchMediaSync::applySettings().

  • Sortie : confirmation settings + nombre de synonymes.

  • Codes : 0 ok · 1 settings KO · 2 settings ok mais synonymes KO (relance sûre).


Non destinés à la production. Ces scripts écrivent en base et sur disque ; ne jamais les lancer sur un environnement réel.

Diagnostique pourquoi un id_token Google échoue à la vérification : header JOSE décodé (kid, alg), payload non vérifié (iss, aud, exp, email…), puis résultat de la vraie vérification signature + claims.

Terminal window
php bin/debug_google_token.php "<id_token>"

test-media-upload.php · test-media-http.php · test-media-glide.php · test-media-crud.php

Section titled “test-media-upload.php · test-media-http.php · test-media-glide.php · test-media-crud.php”

Harnais de test ad-hoc du pipeline média. Ils fabriquent un JPEG synthétique via Imagick, ciblent le premier utilisateur confirmé trouvé en base, et exercent respectivement :

  • test-media-upload.php — l’upload via le service domaine (pHash, etc.).
  • test-media-http.php — l’upload via une requête PSR-7 (3 slots de fichier).
  • test-media-glide.php — l’upload puis la transformation Glide.
  • test-media-crud.php — le cycle CRUD complet, y compris le cas interdit (média d’un autre utilisateur). ⚠️ Purge les médias existants de l’utilisateur de test pour être déterministe.
Terminal window
php bin/test-media-crud.php

Aucun argument ni flag — tout est câblé en dur dans le script.