"array"])] public function getDescription(string|ResourceInterface $resource): array { if (!property_exists($resource, 'latitude') || !property_exists($resource, 'longitude')) { throw new \RuntimeException('DistanceFilter can only used with resources having both latitude and longitude properties'); } return [ 'search' => [ 'property' => 'withinDistance', 'type' => 'string', 'required' => false, 'swagger' => [ 'description' => "Filtre une entity selon sa distance (km) à un point (latitude, longitude). " . "L'entité doit-elle aussi posséder des propriétés 'latitude' et 'longitude'." . "Pass the following query to use it : `withinDistance=({latitude}, {longitude}, {distance})`, " . "where {latitude} and {longitude} are the coordinates of the origine point, and {distance} the maximum distance in Km.", 'name' => 'Distance Filter', 'type' => 'Utils Filter', ], ] ]; } protected function filterProperty( string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null ): void { if ($property !== 'withinDistance') { return; } if (!preg_match('/^(\d+(\.\d+)?,){2}\d+(\.\d+)?$/', $value)) { throw new \RuntimeException('DistanceFilter : Invalid argument, please pass latitude, longitude and distance to the parameter as comma separated floating numbers.'); } [$latitude, $longitude, $distance] = explode(',', $value); $alias = $queryBuilder->getRootAliases()[0]; // Generate unique parameters names to avoid collisions with other filters $latitudeParameterName = $queryNameGenerator->generateParameterName('latitude'); $longitudeParameterName = $queryNameGenerator->generateParameterName('longitude'); $distanceParameterName = $queryNameGenerator->generateParameterName('distance'); $queryBuilder ->andWhere( sprintf( 'SPHERICAL_DISTANCE(%1$s.latitude, %1$s.longitude, :%2$s, :%3$s) <= :%4$s', $alias, $latitudeParameterName, $longitudeParameterName, $distanceParameterName ) ) ->setParameter($latitudeParameterName, $latitude) ->setParameter($longitudeParameterName, $longitude) ->setParameter($distanceParameterName, $distance); } }