findAll(); $features = []; foreach ($statsList as $stats) { // Calcul du barycentre des commerces de la zone $lat = null; $lon = null; $places = $stats->getPlaces(); $count = 0; $sumLat = 0; $sumLon = 0; foreach ($places as $place) { if ($place->getLat() && $place->getLon()) { $sumLat += $place->getLat(); $sumLon += $place->getLon(); $count++; } } if ($count > 0) { $lat = $sumLat / $count; $lon = $sumLon / $count; } $feature = [ 'type' => 'Feature', 'geometry' => $lat && $lon ? [ 'type' => 'Point', 'coordinates' => [$lon, $lat], ] : null, 'properties' => [ 'id' => $stats->getId(), 'name' => $stats->getName(), 'zone' => $stats->getZone(), 'completion_percent' => $stats->getCompletionPercent(), 'places_count' => $stats->getPlacesCount(), 'avec_horaires' => $stats->getAvecHoraires(), 'avec_adresse' => $stats->getAvecAdresse(), 'avec_site' => $stats->getAvecSite(), 'avec_accessibilite' => $stats->getAvecAccessibilite(), 'avec_note' => $stats->getAvecNote(), 'population' => $stats->getPopulation(), 'siren' => $stats->getSiren(), 'codeEpci' => $stats->getCodeEpci(), 'codesPostaux' => $stats->getCodesPostaux(), 'date_created' => $stats->getDateCreated() ? $stats->getDateCreated()->format('c') : null, 'date_modified' => $stats->getDateModified() ? $stats->getDateModified()->format('c') : null, ], ]; $features[] = $feature; } $geojson = [ 'type' => 'FeatureCollection', 'features' => $features, 'meta' => [ 'generated_at' => (new \DateTime())->format('c'), 'source' => 'https://osm-commerces.cipherbliss.com/api/v1/stats_geojson' ] ]; return new JsonResponse($geojson, Response::HTTP_OK, [ 'Content-Type' => 'application/geo+json' ]); } #[Route('/api/v1/stats/{insee}', name: 'api_stats_by_insee', methods: ['GET'])] public function statsByInsee(StatsRepository $statsRepository, string $insee): JsonResponse { $stats = $statsRepository->findOneBy(['zone' => $insee]); if (!$stats) { return new JsonResponse(['error' => 'Zone non trouvée'], Response::HTTP_NOT_FOUND); } $data = [ 'id' => $stats->getId(), 'name' => $stats->getName(), 'zone' => $stats->getZone(), 'completion_percent' => $stats->getCompletionPercent(), 'places_count' => $stats->getPlacesCount(), 'avec_horaires' => $stats->getAvecHoraires(), 'avec_adresse' => $stats->getAvecAdresse(), 'avec_site' => $stats->getAvecSite(), 'avec_accessibilite' => $stats->getAvecAccessibilite(), 'avec_note' => $stats->getAvecNote(), 'population' => $stats->getPopulation(), 'siren' => $stats->getSiren(), 'codeEpci' => $stats->getCodeEpci(), 'codesPostaux' => $stats->getCodesPostaux(), 'date_created' => $stats->getDateCreated() ? $stats->getDateCreated()->format('c') : null, 'date_modified' => $stats->getDateModified() ? $stats->getDateModified()->format('c') : null, ]; return new JsonResponse($data, Response::HTTP_OK); } #[Route('/api/v1/stats/{insee}/places', name: 'api_stats_places_by_insee', methods: ['GET'])] public function statsPlacesByInsee(StatsRepository $statsRepository, string $insee): JsonResponse { $stats = $statsRepository->findOneBy(['zone' => $insee]); if (!$stats) { return new JsonResponse(['error' => 'Zone non trouvée'], Response::HTTP_NOT_FOUND); } $features = []; foreach ($stats->getPlaces() as $place) { $lat = $place->getLat(); $lon = $place->getLon(); $feature = [ 'type' => 'Feature', 'geometry' => ($lat && $lon) ? [ 'type' => 'Point', 'coordinates' => [$lon, $lat], ] : null, 'properties' => [ 'id' => $place->getId(), 'name' => $place->getName(), 'main_tag' => $place->getMainTag(), 'osmId' => $place->getOsmId(), 'email' => $place->getEmail(), 'note' => $place->getNote(), 'zip_code' => $place->getZipCode(), 'siret' => $place->getSiret(), 'has_opening_hours' => $place->hasOpeningHours(), 'has_address' => $place->hasAddress(), 'has_website' => $place->hasWebsite(), 'has_wheelchair' => $place->hasWheelchair(), 'has_note' => $place->hasNote(), 'completion_percent' => $place->getCompletionPercentage(), ], ]; $features[] = $feature; } $geojson = [ 'type' => 'FeatureCollection', 'features' => $features, 'meta' => [ 'generated_at' => (new \DateTime())->format('c'), 'source' => 'https://osm-commerces.cipherbliss.com/api/v1/stats/by_insee/' . $insee . '/places' ] ]; return new JsonResponse($geojson, Response::HTTP_OK, [ 'Content-Type' => 'application/geo+json' ]); } #[Route('/api/v1/stats/by_insee/{insee}/places.csv', name: 'api_stats_places_csv_by_insee', methods: ['GET'])] public function statsPlacesCsvByInsee(StatsRepository $statsRepository, string $insee): StreamedResponse { $stats = $statsRepository->findOneBy(['zone' => $insee]); if (!$stats) { $response = new StreamedResponse(); $response->setCallback(function() { echo 'error\nZone non trouvée'; }); $response->headers->set('Content-Type', 'text/csv'); $response->setStatusCode(Response::HTTP_NOT_FOUND); return $response; } $response = new StreamedResponse(function() use ($stats) { $handle = fopen('php://output', 'w'); // En-têtes CSV fputcsv($handle, [ 'id', 'name', 'main_tag', 'osmId', 'email', 'note', 'zip_code', 'siret', 'lat', 'lon', 'has_opening_hours', 'has_address', 'has_website', 'has_wheelchair', 'has_note' ]); foreach ($stats->getPlaces() as $place) { fputcsv($handle, [ $place->getId(), $place->getName(), $place->getMainTag(), $place->getOsmId(), $place->getEmail(), $place->getNote(), $place->getZipCode(), $place->getSiret(), $place->getLat(), $place->getLon(), $place->hasOpeningHours(), $place->hasAddress(), $place->hasWebsite(), $place->hasWheelchair(), $place->hasNote(), $place->getCompletionPercentage(), ]); } fclose($handle); }); $response->headers->set('Content-Type', 'text/csv'); $response->headers->set('Content-Disposition', 'attachment; filename="places_'.$insee.'.csv"'); return $response; } }