# Fix: FreePBX 17 "Undefined array key trunk_name" on fwconsole reload

## Environment
- FreePBX 17 (Sangoma FreePBX Distro)
- OS: Debian 12 (bookworm)
- Asterisk: PJSIP driver
- Trunk: Single PJSIP trunk (FirstDigital)

## Problem

`fwconsole reload` fails with:

```
In PJSip.class.php line 504:
  Undefined array key "trunk_name"
```

This prevents any configuration changes made in the FreePBX GUI from being applied to Asterisk. DIDs, transfers, and other call routing changes silently fail to take effect.

## Diagnosis

### The Bug

The `getAllTrunks()` method in `PJSip.class.php` (line ~1606) uses this SQL query:

```sql
SELECT id, keyword, data FROM pjsip as tech
LEFT OUTER JOIN trunks ON (tech.id = trunks.trunkid) OR (tech.id = trunks.trunkid)
WHERE trunks.disabled = 'off' OR trunks.disabled IS NULL
```

The `trunks.disabled IS NULL` condition catches rows from the `pjsip` table that have **no matching entry in the `trunks` table** — which includes all **extension** data (extensions 201, 202, 235, etc. are stored in the same `pjsip` table). Extensions don't have a `trunk_name` field, so line 504 crashes:

```php
$tn = $trunk['trunk_name'];  // line 504 - crashes for extensions
```

### Additional Issue: Orphaned Trunk Data

We also found an orphaned trunk in the `pjsip` table:

```sql
SELECT id, keyword, data FROM pjsip WHERE keyword='trunk_name';
-- Returns:
-- id=1, trunk_name=FirstDigital      (valid - exists in trunks table)
-- id=2, trunk_name=FirstDigital_SIP  (orphan - NO matching entry in trunks table)
```

This orphan was likely created by a partially-deleted trunk configuration.

### Side Effect: Broken Logging

We also discovered that `/var/log/asterisk/full` was empty — the logger had no file output configured. This masked the problem since no call errors were being recorded.

## Fix

### Step 1: Patch PJSip.class.php

File location:
```
/var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php
```

Backup first:
```bash
cp /var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php \
   /var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php.bak
```

Replace line 504:
```php
// BEFORE (line 504):
$tn = $trunk['trunk_name'];

// AFTER:
$tn = $trunk['trunk_name'] ?? null; if ($tn === null) { continue; }
```

Using sed:
```bash
sed -i "504s/.*/\t\t\t\$tn = \$trunk['trunk_name'] ?? null; if (\$tn === null) { continue; }/" \
  /var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php
```

### Step 2: Clean Up Orphaned Trunk Data (if present)

Check for orphans:
```sql
-- Run in mysql:
SELECT p.id, p.data FROM pjsip p
WHERE p.keyword='trunk_name'
AND p.id NOT IN (SELECT trunkid FROM trunks);
```

Remove any orphans found:
```sql
-- Replace '2' with the orphaned ID from the query above
DELETE FROM pjsip WHERE id='2';
```

### Step 3: Restore Asterisk Logging

If `/var/log/asterisk/full` is empty and `logger show channels` shows no file output:

```bash
echo 'full => notice,warning,error,verbose,dtmf,fax' > /etc/asterisk/logger_logfiles_custom.conf
```

### Step 4: Reload

```bash
fwconsole reload
# Should output: Reload Complete (no errors)
```

Verify logging:
```bash
asterisk -rx "logger show channels"
# Should show: /var/log/asterisk/full  File  default  Enabled
```

## Verification

```bash
# Reload should succeed cleanly
fwconsole reload
# Output: Reload Started / Reload Complete

# Asterisk should be logging
wc -l /var/log/asterisk/full
# Should be non-zero and growing

# Trunk should be connected
asterisk -rx "pjsip show endpoint <trunk_name>"
# Contact status should show "Avail"
```

## Important Notes

- **This patch will be overwritten on FreePBX module updates.** After running `fwconsole ma updateall` or updating the Core module, check if the fix is still in place.
- The root cause is a bug in FreePBX's `getAllTrunks()` SQL query that doesn't properly filter extensions from trunk data. An upstream fix would modify the query to use `INNER JOIN` or add a `WHERE` clause filtering on `pjsip.keyword = 'trunk_name'`.
- The orphaned trunk data suggests a trunk was deleted through the GUI but the `pjsip` table wasn't fully cleaned up — a separate FreePBX bug.
