• 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

14.29
/iznik-batch/app/Models/UserAddress.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
/**
10
 * @property int $id
11
 * @property int $userid
12
 * @property int|null $pafid
13
 * @property string|null $to
14
 * @property string|null $instructions
15
 * @property float|null $lat
16
 * @property float|null $lng
17
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress newModelQuery()
18
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress newQuery()
19
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress query()
20
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress whereId($value)
21
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress whereInstructions($value)
22
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress whereLat($value)
23
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress whereLng($value)
24
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress wherePafid($value)
25
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress whereTo($value)
26
 * @method static \Illuminate\Database\Eloquent\Builder<static>|UserAddress whereUserid($value)
27
 * @mixin \Eloquent
28
 */
29
class UserAddress extends Model implements Auditable
30
{
31
    use \OwenIt\Auditing\Auditable;
32

33
    protected $table = 'users_addresses';
34
    protected $guarded = ['id'];
35
    public $timestamps = false;
36

37
    protected $casts = [
38
        'lat' => 'float',
39
        'lng' => 'float',
40
    ];
41

42
    /**
43
     * Get formatted address string from PAF data.
44
     *
45
     * @param string $delimiter Delimiter between address parts (', ' for single line, "\n" for multiline)
46
     */
47
    public function getFormatted(string $delimiter = ', '): ?string
3✔
48
    {
49
        if (!$this->pafid) {
3✔
50
            return null;
3✔
51
        }
52

53
        // Build query to get all PAF address parts with their reference values.
54
        $address = DB::table('paf_addresses')
×
55
            ->leftJoin('locations', 'locations.id', '=', 'paf_addresses.postcodeid')
×
56
            ->leftJoin('paf_posttown', 'paf_posttown.id', '=', 'paf_addresses.posttownid')
×
57
            ->leftJoin('paf_dependentlocality', 'paf_dependentlocality.id', '=', 'paf_addresses.dependentlocalityid')
×
58
            ->leftJoin('paf_doubledependentlocality', 'paf_doubledependentlocality.id', '=', 'paf_addresses.doubledependentlocalityid')
×
59
            ->leftJoin('paf_thoroughfaredescriptor', 'paf_thoroughfaredescriptor.id', '=', 'paf_addresses.thoroughfaredescriptorid')
×
60
            ->leftJoin('paf_dependentthoroughfaredescriptor', 'paf_dependentthoroughfaredescriptor.id', '=', 'paf_addresses.dependentthoroughfaredescriptorid')
×
61
            ->leftJoin('paf_buildingname', 'paf_buildingname.id', '=', 'paf_addresses.buildingnameid')
×
62
            ->leftJoin('paf_subbuildingname', 'paf_subbuildingname.id', '=', 'paf_addresses.subbuildingnameid')
×
63
            ->leftJoin('paf_pobox', 'paf_pobox.id', '=', 'paf_addresses.poboxid')
×
64
            ->leftJoin('paf_departmentname', 'paf_departmentname.id', '=', 'paf_addresses.departmentnameid')
×
65
            ->leftJoin('paf_organisationname', 'paf_organisationname.id', '=', 'paf_addresses.organisationnameid')
×
66
            ->select([
×
67
                'locations.name as postcode',
×
68
                'paf_addresses.buildingnumber',
×
69
                'paf_posttown.posttown',
×
70
                'paf_dependentlocality.dependentlocality',
×
71
                'paf_doubledependentlocality.doubledependentlocality',
×
72
                'paf_thoroughfaredescriptor.thoroughfaredescriptor',
×
73
                'paf_dependentthoroughfaredescriptor.dependentthoroughfaredescriptor',
×
74
                'paf_buildingname.buildingname',
×
75
                'paf_subbuildingname.subbuildingname',
×
76
                'paf_pobox.pobox',
×
77
                'paf_departmentname.departmentname',
×
78
                'paf_organisationname.organisationname',
×
79
            ])
×
80
            ->where('paf_addresses.id', $this->pafid)
×
81
            ->first();
×
82

83
        if (!$address) {
×
84
            return null;
×
85
        }
86

87
        // Build address lines following Royal Mail PAF formatting rules.
88
        $lines = [];
×
89

90
        // Organisation/department
91
        if ($address->organisationname) {
×
92
            $lines[] = $address->organisationname;
×
93
        }
94
        if ($address->departmentname) {
×
95
            $lines[] = $address->departmentname;
×
96
        }
97

98
        // PO Box
99
        if ($address->pobox) {
×
100
            $lines[] = 'PO Box ' . $address->pobox;
×
101
        }
102

103
        // Sub-building name (e.g., "Flat 1")
104
        if ($address->subbuildingname) {
×
105
            $lines[] = $address->subbuildingname;
×
106
        }
107

108
        // Building name or number + street
109
        $streetLine = '';
×
110
        if ($address->buildingname) {
×
111
            $lines[] = $address->buildingname;
×
112
        }
113
        if ($address->buildingnumber) {
×
114
            $streetLine = $address->buildingnumber;
×
115
        }
116
        if ($address->dependentthoroughfaredescriptor) {
×
117
            $streetLine .= ($streetLine ? ' ' : '') . $address->dependentthoroughfaredescriptor;
×
118
        }
119
        if ($address->thoroughfaredescriptor) {
×
120
            if ($streetLine && !$address->dependentthoroughfaredescriptor) {
×
121
                $streetLine .= ' ' . $address->thoroughfaredescriptor;
×
122
            } else {
123
                $lines[] = $streetLine;
×
124
                $streetLine = $address->thoroughfaredescriptor;
×
125
            }
126
        }
127
        if ($streetLine) {
×
128
            $lines[] = $streetLine;
×
129
        }
130

131
        // Locality
132
        if ($address->doubledependentlocality) {
×
133
            $lines[] = $address->doubledependentlocality;
×
134
        }
135
        if ($address->dependentlocality) {
×
136
            $lines[] = $address->dependentlocality;
×
137
        }
138

139
        // Post town and postcode
140
        $townPostcode = trim(($address->posttown ?? '') . ' ' . ($address->postcode ?? ''));
×
141
        if ($townPostcode) {
×
142
            $lines[] = $townPostcode;
×
143
        }
144

145
        // Filter empty lines and join
146
        $lines = array_filter($lines, fn($line) => !empty(trim($line)));
×
147

148
        // Apply tweaks similar to iznik-server
149
        if (count($lines) >= 2 && str_starts_with($lines[1] ?? '', ($lines[0] ?? '') . ' ')) {
×
150
            array_shift($lines);
×
151
        }
152

153
        return implode($delimiter, $lines);
×
154
    }
155

156
    /**
157
     * Get single-line formatted address.
158
     */
159
    public function getSingleLine(): ?string
1✔
160
    {
161
        return $this->getFormatted(', ');
1✔
162
    }
163

164
    /**
165
     * Get multi-line formatted address.
166
     */
167
    public function getMultiLine(): ?string
1✔
168
    {
169
        return $this->getFormatted("\n");
1✔
170
    }
171

172
    /**
173
     * Get coordinates for this address.
174
     * Falls back to postcode location if address doesn't have direct lat/lng.
175
     *
176
     * @return array [lat, lng] or [null, null]
177
     */
178
    public function getCoordinates(): array
2✔
179
    {
180
        // Use direct coordinates if available.
181
        if ($this->lat && $this->lng) {
2✔
182
            return [$this->lat, $this->lng];
1✔
183
        }
184

185
        // Fall back to postcode coordinates via PAF.
186
        if (!$this->pafid) {
1✔
187
            return [null, null];
1✔
188
        }
189

190
        $location = DB::table('paf_addresses')
×
191
            ->join('locations', 'locations.id', '=', 'paf_addresses.postcodeid')
×
192
            ->where('paf_addresses.id', $this->pafid)
×
193
            ->select(['locations.lat', 'locations.lng'])
×
194
            ->first();
×
195

196
        if ($location) {
×
197
            return [$location->lat, $location->lng];
×
198
        }
199

200
        return [null, null];
×
201
    }
202
}
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