# Running it on your own machine

For trying the system, training staff, or testing an import before touching the
parish server. Fifteen minutes.

---

## What you need

- **PHP 8.1 or newer** with these extensions: `pdo_mysql`, `mbstring`, `curl`,
  `openssl`, `simplexml`, `zip`
- **MySQL 8.0** or **MariaDB 10.6+**

Check what you have:

```bash
php -v
php -m | grep -E "pdo_mysql|mbstring|curl|openssl|SimpleXML|zip"
```

You should see six lines. `SimpleXML` and `zip` are only needed by the workbook
importer — everything else runs without them.

**Windows:** install [XAMPP](https://www.apachefriends.org) or
[Laragon](https://laragon.org). Both bundle PHP and MariaDB.
**macOS:** `brew install php mysql` then `brew services start mysql`.
**Ubuntu/Debian:**

```bash
sudo apt install php-cli php-mysql php-mbstring php-curl php-xml php-zip mariadb-server
sudo systemctl start mariadb
```

---

## 1. Unpack

```bash
unzip pcea-chms-1.4.0.zip
cd pcea-chms-1.4.0
mkdir -p storage/backups
```

On XAMPP, put the folder in `C:\xampp\htdocs\` — but see the note about the
document root below, because it matters.

---

## 2. Create the database

The character set is not optional: without `utf8mb4`, Kenyan names and Swahili
are stored wrong and the installer will refuse to continue.

```bash
mysql -u root -p -e "CREATE DATABASE pcea_chms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
```

On XAMPP use phpMyAdmin: **New** → name `pcea_chms` → collation
`utf8mb4_unicode_ci` → Create.

For a local trial you can use the `root` account. Do not do that on a real
server — pre-flight will tell you so.

---

## 3. Start the server

```bash
php -S localhost:8000 -t public
```

**`-t public` is the important part.** It points the web server at the `public`
folder, so everything above it — `src/`, `sql/`, `tools/`, and the `.env` holding
your database password — cannot be requested over HTTP. Leave it out and those
files are downloadable.

Leave that terminal running. Stop it with Ctrl-C.

### On XAMPP or MAMP instead

Those serve `htdocs` directly, which would expose the folders above `public`.
Either use the command above (simplest — PHP is already installed by XAMPP), or
point a virtual host at the `public` subfolder. The included
`public/.htaccess` does the rest.

---

## 4. Install

Open **http://localhost:8000/install.php** and work through four steps:

| Step | What to enter |
|---|---|
| Requirements | Everything must pass except the HTTPS warning — expected on localhost |
| Database | Host `127.0.0.1`, port `3306`, name `pcea_chms`, your MySQL user |
| Parish | Name, districts one per line, financial year (PCEA runs July–June) |
| Administrator | Your name, an email, and a password — or leave it blank for a generated one |

**If the database step fails with "could not reach the database"**, your MySQL
is on a socket rather than a port. Leave the host as-is and fill in the socket
path field:

- Linux: `/var/run/mysqld/mysqld.sock`
- macOS (Homebrew): `/tmp/mysql.sock`
- XAMPP: usually TCP on 3306, so leave the socket blank

Then sign in at **http://localhost:8000/login.php** and work down the setup
checklist the dashboard shows you.

---

## 5. Optional: sample data

To see the system full rather than empty — twelve districts, forty weeks, six
thousand contributions:

```bash
DB_NAME=pcea_chms DB_USER=root DB_PASS=yourpassword php tools/seed.php
```

**This truncates every table.** Never run it against a database holding real
parish records. It prints the sign-in accounts it creates.

---

## Things that will not work on localhost, and that is correct

- **M-Pesa callbacks.** Safaricom cannot reach your laptop. Use ngrok if you
  need to test the webhook, or leave it — the rest of the system runs fine.
- **SMS and WhatsApp.** With no API keys set, `php tools/send_queue.php` prints
  what it *would* send, with the per-message cost. That is the intended way to
  check the wording before anything reaches a member.
- **Install to home screen.** Needs HTTPS. `localhost` is treated as secure by
  Chrome, so it usually works there anyway.

---

## When you are finished testing

```bash
rm public/install.php        # or delete it in Explorer/Finder
php tools/preflight.php
```

Pre-flight will list what would be unsafe on a real server. On localhost you can
ignore the M-Pesa and backup warnings; on a parish server you cannot.

---

## If something goes wrong

| Symptom | Cause |
|---|---|
| Page is blank | A PHP error. Errors go to the log, never the browser — check your terminal, where `php -S` prints them |
| "Database unavailable" | MySQL is not running, or the credentials in `.env` are wrong |
| Directory listing instead of the app | You omitted `-t public` |
| "not an .xlsx file" on import | It is an older `.xls`. Open in Excel and Save As `.xlsx` |
| Styles missing | You opened a file directly instead of through `http://localhost:8000` |

To start completely over: drop the database, delete `.env` and
`storage/installed.lock`, and re-run the installer.

## Windows: just double-click

For a parish office PC, the three files in the root of this package do
everything described below without a command line:

| File | What it does |
|---|---|
| `START PCEA CHMS.bat` | Finds PHP and MySQL, creates the database and its own database account, imports the schema, applies any updates, checks this computer, starts the server and opens the browser. |
| `STOP PCEA CHMS.bat` | Frees the port when the server window was closed the hard way. |
| `RESET DATABASE.bat` | Wipes the local database back to a fresh install. Type RESET to confirm. |

Put the folder somewhere writable — `C:\pcea` is ideal, **not** inside
Program Files — install XAMPP if PHP and MySQL are not already there, and
double-click the first file.

**First run** opens the setup page with the database details already filled
in; you choose the parish name and your administrator password. **Later runs**
open the sign-in page. If the database was made by an older version, the
launcher applies the outstanding migrations first and says so.

Things it handles that catch people out:

- **The web root is `public\`, never the project folder.** Serving the folder
  above would put `.env`, the source and the backups on the web. The launcher
  passes `-t "%ROOT%\public"` and this was verified: `/.env`, `/sql/install.sql`,
  `/src/...` and `/tools/...` all return 404.
- **Port 8080 is often reserved by Windows** (Hyper-V, WSL and Docker reserve
  ranges silently; netstat still shows the port free). The launcher *binds* a
  test socket and walks a fallback list — 8081, 8088, 8090, 8899, 9090, 8123 —
  until one works, and tells you which it used.
- **PHP 8.0 will not do.** The launcher refuses with the version it found and
  what to install, rather than letting a page fatal later.
- **Missing extensions** (`pdo_mysql`, `mbstring`, `simplexml`, `zip`) are named
  individually, with the line to uncomment in `php.ini`.
- **A stale `.env`** — one copied from the live site — is rewritten with local
  settings before any PHP step runs, so a local launcher can never point at the
  parish's real database. Non-database keys you added are preserved.

To clear practice data but keep real work, do **not** use RESET DATABASE — open
Settings inside the system and press *Remove the practice data*.

### Schema updates

`php tools\migrate.php --status` lists what is applied. The launcher runs
`migrate.php` on every start; `--baseline-all` is used only right after a fresh
import, because `install.sql` already contains every migration.

