58 lines
2.7 KiB
PHP
58 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Database\Query\Builder;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
/** Disclosure is decided by the stored public flag and declared precision, never inferred from an address. */
|
|
final class PublicBusinessLocations
|
|
{
|
|
/** @return literal-string */
|
|
public function sourceProjection(): string
|
|
{
|
|
return app(BusinessPointPublication::class)->available()
|
|
? 'l.public_source_reference AS location_source_reference, l.source_date AS location_source_date'
|
|
: 'NULL::text AS location_source_reference, NULL::date AS location_source_date';
|
|
}
|
|
|
|
public function disclosed(): Builder
|
|
{
|
|
$query = DB::table('existing_business_locations as l')->where('l.is_public', true);
|
|
foreach (['province_id' => ['province', 'district', 'admin_post', 'locality', 'exact'],
|
|
'district_id' => ['district', 'admin_post', 'locality', 'exact'],
|
|
'admin_post_id' => ['admin_post', 'locality', 'exact'], 'locality_id' => ['locality', 'exact']] as $field => $precisions) {
|
|
$query->where(fn (Builder $scope) => $scope->whereNotIn('l.precision_level', $precisions)->orWhereNull('l.'.$field)
|
|
->orWhereIn('l.'.$field, app(InvestmentGeography::class)->publicReferences()->select('id')));
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
public function primary(): Builder
|
|
{
|
|
return $this->disclosed()->where('l.is_primary', true);
|
|
}
|
|
|
|
public function points(): Builder
|
|
{
|
|
// Nested CASE is intentional: ST_X/ST_Y must never receive a polygon or collection.
|
|
return $this->primary()->where('l.precision_level', 'exact')
|
|
->select('l.existing_business_id', 'l.updated_at as location_recorded_at')
|
|
->selectRaw($this->sourceProjection())
|
|
->selectRaw("CASE WHEN GeometryType(l.geom)='POINT' AND ST_IsValid(l.geom) AND NOT ST_IsEmpty(l.geom) AND ST_SRID(l.geom)=4326
|
|
THEN CASE WHEN ST_X(l.geom) BETWEEN -180 AND 180 AND ST_Y(l.geom) BETWEEN -90 AND 90 THEN l.geom END END AS point");
|
|
}
|
|
|
|
/** @param list<string> $ids */
|
|
public function matchingArea(array $ids): Builder
|
|
{
|
|
return $this->disclosed()->where(function (Builder $query) use ($ids): void {
|
|
$query->whereIn('l.province_id', $ids)
|
|
->orWhere(fn (Builder $level) => $level->whereIn('l.precision_level', ['district', 'admin_post', 'locality', 'exact'])->whereIn('l.district_id', $ids))
|
|
->orWhere(fn (Builder $level) => $level->whereIn('l.precision_level', ['admin_post', 'locality', 'exact'])->whereIn('l.admin_post_id', $ids))
|
|
->orWhere(fn (Builder $level) => $level->whereIn('l.precision_level', ['locality', 'exact'])->whereIn('l.locality_id', $ids));
|
|
});
|
|
}
|
|
}
|