# Production files to pull locally

Everything under `companies/` is outside version control, so none of it can be
analysed or fixed from the dev box. Three independent signals prove the local
copies have **drifted** from production and cannot be trusted as a stand-in:

| File | Local | Production |
|---|---|---|
| `testandtag/functions.php` | line 3, absolute dev path to `.env` | line 2, `../../../../.env` — resolves nowhere, 1,215 failures logged |
| `testandtag/siteedit.php:220` | plain HTML markup | a `foreach()` over a non-array |
| `testandtag/reports/f1_det.php:90` | `array_push($csv,…)` | identical — this one **does** match |

So local is neither newer nor older overall; the two copies have diverged
independently. **Production is authoritative** — pull it, fix it there or here,
upload the result.

Production root, from the error log paths: `/home/evolution/my.evolutionerp.com.au`

---

## 1. Pull these — needed to fix known PHP 8 fatals

### a. The legacy testandtag plugin (whole directory)

```
companies/85-1516155235/plugins/
```

34 PHP files, ~4,900 LOC. Contains the only confirmed PHP 8 fatal in tenant
code (`array_push()` on null, 197 hits) and is the subject of the migration
scope doc. Pull the **whole** `plugins/` directory, not just the three files
the log named — the log only shows what someone happened to run in 9 days, and
the same `$csv` bug is present in at least 6 files locally.

```bash
rsync -avz --exclude='backups/' \
  prod:/home/evolution/my.evolutionerp.com.au/companies/85-1516155235/plugins/ \
  ./prod-pull/85-1516155235/plugins/
```

### b. Two print templates with hard fatals

```
companies/108-1481181613/files/Pricebook_No_RRP.html
companies/108-1481181613/files/invoicedefault.html
```

202 `Use of undefined constant` warnings between them. This is the one class
that is an **unconditional fatal** in PHP 8 (`Error: Undefined constant "x"`),
not a downgrade-able warning. These files are `include()`d as PHP, so they need
the same bareword-key fix the repo got in Tier 2. Neither file exists locally.

### c. The `.docx` being executed as PHP

```
companies/85-1559715131/files/job/2018/611c27ba0dde6.docx
```

5 parse errors logged. Something is `include()`ing a Word document. That is a
bug independent of the migration and possibly a local-file-include concern —
worth seeing the file *and* finding the caller. Low volume, high interest.

---

## 2. Enumerate first — we don't know what we don't know

The dev box has 21 tenant directories; production certainly has more, and the
error log only reveals tenants whose code *ran and failed* during the 9-day
window. Before deciding what else to pull, get a full inventory.

Run on production (read-only, no writes, a few seconds):

```bash
cd /home/evolution/my.evolutionerp.com.au/companies

# every tenant that ships executable PHP, and how much
for d in */; do
  n=$(find "$d" -name '*.php' -not -path '*/backups/*' 2>/dev/null | wc -l)
  t=$(find "$d/files" \( -name '*.html' -o -name '*.htm' \) 2>/dev/null | wc -l)
  [ "$n" -gt 0 -o "$t" -gt 0 ] && printf '%-24s php=%-4s templates=%s\n' "${d%/}" "$n" "$t"
done
```

Any tenant with `php>0` is a blind spot. Any tenant with `templates>0` may carry
the bareword-key fatal. Send that output back and I will turn it into a
prioritised pull list.

---

## 3. Then run the scanner

`php8-scan.php` (now in the repo at `evolution/cron/php8-migration/`, so it is
already on the prod box after a pull) is written for **PHP 7.4** so it runs
on production as-is. It is read-only by default.

```bash
# read-only, writes php8-findings.txt next to the script
cd /home/evolution/my.evolutionerp.com.au/evolution/cron/php8-migration
php php8-scan.php /home/evolution/my.evolutionerp.com.au/companies

# optional: auto-fix ONLY bareword array keys, with .php8bak backups
php php8-scan.php /home/evolution/my.evolutionerp.com.au/companies --apply
```

It reports five classes and only ever rewrites class A:

| Class | Meaning | Auto-fixed |
|---|---|---|
| A | bareword array key → `Error: Undefined constant` | **yes** — token-level, lint-checked, backed up |
| B | array initialised inside an `if()` but used outside it | no — reports the exact line to move |
| C | array builtin on a variable with no visible initialiser | no — needs the caller's context |
| D | division by a possibly-zero variable | no — the safe default differs per site |
| E | function removed in PHP 8 (`each`, `create_function`, …) | no |

Against the local tree it found 43 issues, including the `$csv` bug in **6**
files — one more than I found by hand — so it is worth running even on
directories we think we understand.

Rollback if `--apply` goes wrong:

```bash
find <root> -name '*.php8bak' -exec sh -c 'mv "$1" "${1%.php8bak}"' _ {} \;
```

---

## 4. Two things to fix on production regardless of PHP 8

- **`testandtag/functions.php` cannot load `.env`.** It includes
  `../../../../.env`, which does not resolve from its location — 2,430 warnings
  in 9 days, the single noisiest line in the log. Whatever config it wanted, it
  has been silently going without.
- **Hardcoded database credentials.** The plugin connects to an external MySQL
  server with the same username and password written into at least six files
  (`functions.php`, `reports/26/r1.php`, `r2.php`, `r3.php`, `reports/38/all-in.php`,
  and others). These sit in an untracked, world-readable directory. See the
  migration scope doc.
