• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Freegle / Iznik / 20959

13 Jun 2026 02:43PM UTC coverage: 71.021% (+1.5%) from 69.555%
20959

push

circleci

edwh
feat(web): redirect /councils to /partnerships

The councils content now lives at /partnerships; add a route rule so the old
/councils URL (which 404'd) redirects there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

10705 of 14260 branches covered (75.07%)

Branch coverage included in aggregate %.

116833 of 165317 relevant lines covered (70.67%)

35.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.92
/iznik-batch/app/Models/Location.php
1
<?php
2

3
namespace App\Models;
4

5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Facades\DB;
7
use OwenIt\Auditing\Contracts\Auditable;
8

9
class Location extends Model implements Auditable
10
{
11
    use \OwenIt\Auditing\Auditable;
12

13
    // Fields exposed by getPublic() - mirrors iznik-server Location::$publicatts.
14
    private const PUBLIC_ATTS = ['id', 'osm_id', 'name', 'type', 'popularity', 'gridid', 'postcodeid', 'areaid', 'lat', 'lng', 'maxdimension'];
15

16
    protected $table = 'locations';
17
    protected $guarded = ['id'];
18
    public $timestamps = false;
19

20
    protected $casts = [
21
        'lat' => 'decimal:6',
22
        'lng' => 'decimal:6',
23
        'osm_place' => 'boolean',
24
        'osm_amenity' => 'boolean',
25
        'osm_shop' => 'boolean',
26
    ];
27

28
    public static function closestPostcode(float $lat, float $lng): ?object
2✔
29
    {
30
        $srid = config('freegle.srid', 3857);
2✔
31
        $scan = 0.00001953125;
2✔
32

33
        do {
34
            $swlat = $lat - $scan;
2✔
35
            $nelat = $lat + $scan;
2✔
36
            $swlng = $lng - $scan;
2✔
37
            $nelng = $lng + $scan;
2✔
38

39
            $poly = "POLYGON(($swlng $swlat, $swlng $nelat, $nelng $nelat, $nelng $swlat, $swlng $swlat))";
2✔
40

41
            $locs = DB::select(
2✔
42
                "SELECT locations.id, locations.name, locations.lat, locations.lng
2✔
43
                 FROM locations_spatial
44
                 INNER JOIN locations ON locations.id = locations_spatial.locationid
45
                 WHERE MBRContains(ST_Envelope(ST_GeomFromText(?, ?)), locations_spatial.geometry)
46
                   AND locations.type = 'Postcode'
47
                   AND LOCATE(' ', locations.name) > 0
48
                 ORDER BY ST_distance(locations_spatial.geometry, ST_GeomFromText(?, ?)) ASC
49
                 LIMIT 1",
2✔
50
                [$poly, $srid, "POINT($lng $lat)", $srid]
2✔
51
            );
2✔
52

53
            if (count($locs) === 1) {
2✔
54
                return $locs[0];
×
55
            }
56

57
            $scan *= 2;
2✔
58
        } while ($scan <= 0.2);
2✔
59

60
        return null;
2✔
61
    }
62

63
    public static function findByName(string $name): ?int
×
64
    {
65
        return static::getByName($name)?->id;
×
66
    }
67

68
    public static function getByName(string $name): ?object
14✔
69
    {
70
        $canon = strtolower(preg_replace("/[^A-Za-z0-9]/", '', $name));
14✔
71
        return DB::table('locations')->where('canon', 'LIKE', $canon)->first();
14✔
72
    }
73

74
    public static function groupsNear(float $lat, float $lng, int $radiusMiles = 50, int $limit = 10): array
21✔
75
    {
76
        $srid     = config('freegle.srid', 3857);
21✔
77
        $pointWkt = "POINT($lng $lat)";
21✔
78

79
        // Polygon-containment check: if the point lies inside one or more group
80
        // polyindex polygons, those groups are authoritative and beat the centroid-
81
        // distance heuristic (V1 parity; fixes Discourse #9763 where a group with
82
        // a close centroid but non-containing polyindex shadowed the correct group).
83
        $containing = DB::select(
21✔
84
            "SELECT id
21✔
85
             FROM `groups`
86
             WHERE publish = 1 AND listable = 1
87
               AND ST_Contains(polyindex, ST_GeomFromText(?, ?))
88
             ORDER BY haversine(lat, lng, ?, ?) ASC
89
             LIMIT ?",
21✔
90
            [$pointWkt, $srid, $lat, $lng, $limit]
21✔
91
        );
21✔
92

93
        if (!empty($containing)) {
21✔
94
            return array_column($containing, 'id');
21✔
95
        }
96

97
        // No group polygon contains the point; fall back to centroid distance.
98
        $rows = DB::select(
×
99
            "SELECT id
×
100
             FROM `groups`
101
             WHERE publish = 1 AND listable = 1
102
               AND haversine(lat, lng, ?, ?) < ?
103
             ORDER BY haversine(lat, lng, ?, ?) ASC
104
             LIMIT ?",
×
105
            [$lat, $lng, $radiusMiles, $lat, $lng, $limit]
×
106
        );
×
107

108
        return array_column($rows, 'id');
×
109
    }
110
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc