Skip to content

Commit

Permalink
Replaced the DISTANCE function with the new DISTANCE_IN_METERS one.
Browse files Browse the repository at this point in the history
Instead of keeping BC, we simply fix the broken function.
  • Loading branch information
kimlai committed Jul 24, 2014
1 parent a2b8dfc commit 9d4b117
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 117 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"require-dev": {
"ext-pdo_sqlite": "*",
"ext-pdo_pgsql": "*",
"doctrine/orm": ">=2.2",
"doctrine/mongodb-odm": "dev-master",
"phpunit/phpunit": "~3.7"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,6 @@ public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
$em->getConfiguration()->addCustomNumericFunction(
'DISTANCE', 'Knp\DoctrineBehaviors\ORM\Geocodable\Query\AST\Functions\DistanceFunction'
);

$em->getConfiguration()->addCustomNumericFunction(
'DISTANCE_IN_METERS', 'Knp\DoctrineBehaviors\ORM\Geocodable\Query\AST\Functions\DistanceInMetersFunction'
);
}
}

Expand Down
23 changes: 3 additions & 20 deletions src/Knp/DoctrineBehaviors/ORM/Geocodable/GeocodableRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,16 @@ trait GeocodableRepository
public function findByDistanceQB(Point $point, $distanceMax)
{
return $this->createQueryBuilder('e')
->andWhere('DISTANCE(e.location, :location) <= :distanceMax')
->setParameter('location', $point)
->setParameter('distanceMax', $distanceMax)
;
}

public function findByDistance(Point $point, $distanceMax)
{
return $this->findByDistanceQB($point, $distanceMax)
->getQuery()
->execute()
;
}

public function findByDistanceInMetersQB(Point $point, $distanceMax)
{
return $this->createQueryBuilder('e')
->andWhere('DISTANCE_IN_METERS(e.location, :latitude, :longitude) <= :distanceMax')
->andWhere('DISTANCE(e.location, :latitude, :longitude) <= :distanceMax')
->setParameter('latitude', $point->getLatitude())
->setParameter('longitude', $point->getLongitude())
->setParameter('distanceMax', $distanceMax)
;
}

public function findByDistanceInMeters(Point $point, $distanceMax)
public function findByDistance(Point $point, $distanceMax)
{
return $this->findByDistanceInMetersQB($point, $distanceMax)
return $this->findByDistanceQB($point, $distanceMax)
->getQuery()
->execute()
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\AST\PathExpression;

/**
* DQL function for calculating distances between two points
* DQL function for calculating distances in meters between two points
*
* DISTANCE(entity.point, POINT(:param))
* DISTANCE(entity.point, :latitude, :longitude)
*/
class DistanceFunction extends FunctionNode
{
private $firstArg;
private $secondArg;
private $entityLocation;
private $latitude;
private $longitude;

/**
* Returns SQL representation of this function.
Expand All @@ -26,12 +28,17 @@ class DistanceFunction extends FunctionNode
*/
public function getSql(SqlWalker $sqlWalker)
{
return sprintf('%s <@> %s',
$this->firstArg->dispatch($sqlWalker),
$this->secondArg->dispatch($sqlWalker)
$entityLocation = $this->entityLocation->dispatch($sqlWalker);
return sprintf('earth_distance(ll_to_earth(%s[0], %s[1]),ll_to_earth(%s, %s))',
$entityLocation,
$entityLocation,
$this->latitude->dispatch($sqlWalker),
$this->longitude->dispatch($sqlWalker)
);
}



/**
* Parses DQL function.
*
Expand All @@ -41,9 +48,11 @@ public function parse(Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->firstArg = $parser->ArithmeticPrimary();
$this->entityLocation = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$this->latitude = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_COMMA);
$this->secondArg = $parser->ArithmeticPrimary();
$this->longitude = $parser->ArithmeticPrimary();
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
}

This file was deleted.

33 changes: 7 additions & 26 deletions tests/Knp/DoctrineBehaviors/ORM/GeocodableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,6 @@ public function testGetLocation()
$this->assertInstanceOf('Knp\DoctrineBehaviors\ORM\Geocodable\Type\Point', $entity->getLocation());
}

public function testFindByDistance()
{
$em = $this->getEntityManager(null, null, [
'driver' => 'pdo_pgsql',
'dbname' => 'orm_behaviors_test',
]);

$repo = $em->getRepository('BehaviorFixtures\ORM\GeocodableEntity');

$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 500);
$this->assertCount(1, $cities, 'Paris is less than 500 miles far from Reguisheim');

$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 900);
$this->assertCount(2, $cities, 'Paris and Nantes are less than 900 miles far from Reguisheim');

$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 9000);
$this->assertCount(3, $cities, 'Paris, Nantes and New-York are less than 9000 miles far from Reguisheim');
}

/**
* Geographical info
* Taken from http://andrew.hedges.name/experiments/haversine, I don't know if it's the same
Expand All @@ -102,7 +83,7 @@ public function testFindByDistance()
* Requisheim <-> Nantes ~671 km, ~417 miles
* Requisheim <-> New-York ~6217 km, ~3864 miles
*/
public function testFindByDistanceInMeters()
public function testFindByDistance()
{
$em = $this->getEntityManager(null, null, [
'driver' => 'pdo_pgsql',
Expand All @@ -111,22 +92,22 @@ public function testFindByDistanceInMeters()

$repo = $em->getRepository('BehaviorFixtures\ORM\GeocodableEntity');

$cities = $repo->findByDistanceInMeters(new Point(47.896319, 7.352943), 384000);
$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 384000);
$this->assertCount(0, $cities, 'Paris is more than 384 km far from Reguisheim');

$cities = $repo->findByDistanceInMeters(new Point(47.896319, 7.352943), 385000);
$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 385000);
$this->assertCount(1, $cities, 'Paris is less than 385 km far from Reguisheim');

$cities = $repo->findByDistanceInMeters(new Point(47.896319, 7.352943), 672000);
$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 672000);
$this->assertCount(1, $cities, 'Nantes is more than 672 km far from Reguisheim');

$cities = $repo->findByDistanceInMeters(new Point(47.896319, 7.352943), 673000);
$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 673000);
$this->assertCount(2, $cities, 'Paris and Nantes are less than 673 km far from Reguisheim');

$cities = $repo->findByDistanceInMeters(new Point(47.896319, 7.352943), 6222000);
$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 6222000);
$this->assertCount(2, $cities, 'New-York is more than 6222 km far from Reguisheim');

$cities = $repo->findByDistanceInMeters(new Point(47.896319, 7.352943), 6223000);
$cities = $repo->findByDistance(new Point(47.896319, 7.352943), 6223000);
$this->assertCount(3, $cities, 'Paris, Nantes and New-York are less than 6223 km far from Reguisheim');
}
}

0 comments on commit 9d4b117

Please sign in to comment.