# ABAS Event Management System — Full CodeIgniter 4 Build (No Composer Needed)

This is the **complete, ready-to-run application** — the CodeIgniter 4
framework itself (`system/`) plus this event system's app code (`app/`) —
already merged together. You do **not** need Composer or SSH access. Just
upload and configure through cPanel.

It's built on official CodeIgniter 4.7.4 (downloaded directly from
CodeIgniter's GitHub releases) with this project's controllers, models,
views, and database migrations merged into it. Every file has already been
syntax-checked and the whole flow (event creation → registration → QR code →
attendance scan → Excel export → volunteer sign-up) has been tested end to
end.

## What's in this folder

```
app/            <- this event system: controllers, models, views, migrations
system/         <- the CodeIgniter 4 framework core (don't edit)
public/         <- the web-accessible front door (index.php, .htaccess)
writable/       <- cache, logs, sessions (must be writable by PHP)
.env            <- your configuration (edit this — see below)
spark           <- CLI tool (only usable if your host gives SSH access)
```

## Requirements on your cPanel host

- PHP **8.2 or higher** (set this in cPanel → "MultiPHP Manager" or
  "Select PHP Version")
- PHP extensions: `intl`, `mbstring`, `mysqli`, `curl`, `json` — these are
  enabled by default on virtually all cPanel hosts. If something errors
  about a missing extension, enable it in cPanel → "Select PHP Version" →
  "Extensions".
- A MySQL database (create one via cPanel → "MySQL Databases")

## Step 1 — Create the database

In cPanel → **MySQL Databases**:
1. Create a database (e.g. `yourcpanel_abasevents`)
2. Create a database user with a strong password
3. Add that user to the database with **All Privileges**

Note the database name, username, and password — cPanel typically prefixes
them with your account name (e.g. `myuser_abasevents`).

## Step 2 — Upload the files

You have two options depending on what your host allows.

### Option A — You can set a custom "Document Root" (preferred, more secure)

Some cPanel hosts let you create a subdomain/addon domain with its own
document root folder. If so:

1. Upload this **entire folder** (`abas-events/`) somewhere **outside**
   `public_html`, e.g. into your home directory.
2. Set the domain/subdomain's document root to `abas-events/public`.
3. Everything else (`app/`, `system/`, `writable/`, `.env`) stays outside the
   web root — the most secure setup, since PHP source and your `.env`
   credentials are never directly web-accessible.

### Option B — You only have `public_html` (typical basic shared hosting)

Most basic cPanel plans only give you `public_html` with no way to point it
elsewhere. In that case:

1. Upload this whole `abas-events` folder into your home directory,
   **alongside** `public_html` (not inside it) — e.g. so you end up with
   `/home/yourcpanel/abas-events/` next to `/home/yourcpanel/public_html/`.
2. Copy everything **inside** `abas-events/public/` (i.e. `index.php`,
   `.htaccess`, `robots.txt`, `favicon.ico`) into `public_html/` directly.
3. Edit the `index.php` you just copied into `public_html/` — change these
   two lines near the top:
   ```php
   require FCPATH . '../app/Config/Paths.php';
   ```
   to point at the real location of `app/Config/Paths.php`, e.g. if
   `abas-events` sits next to `public_html`:
   ```php
   require FCPATH . '../abas-events/app/Config/Paths.php';
   ```
4. Edit `abas-events/app/Config/Paths.php` so the four path properties point
   to the right place relative to *that file's own location* (they normally
   don't need changes if you keep `app/`, `system/`, and `writable/` together
   inside `abas-events/` — only `index.php`'s reference to `Paths.php` in
   step 3 needs updating).

**If you're not comfortable editing these paths yourself, ask your host's
support to help point `public_html` at the `public/` folder — this is a
one-line change many cPanel hosts will happily make for you (an "addon
domain" or "subdomain" with a custom document root avoids all of this).**

## Step 3 — Configure `.env`

Open `abas-events/.env` in cPanel's File Manager (or FTP) and edit:

```
CI_ENVIRONMENT = production

app.baseURL = 'https://yourdomain.com/'

database.default.hostname = localhost
database.default.database = yourcpanel_abasevents
database.default.username = yourcpanel_dbuser
database.default.password = your_db_password
database.default.DBDriver = MySQLi
database.default.port = 3306
```

Make sure the file is named exactly `.env` (with the leading dot) — some
File Managers hide dotfiles by default; enable "Show Hidden Files" in
Settings if you don't see it.

## Step 4 — Run the database migrations

The migrations create all tables **and** a default admin login
(`admin` / `Admin@123`). You have two ways to run them:

**If your host gives you SSH / Terminal access** (cPanel → Terminal):
```bash
cd abas-events
php spark migrate
```

**If you don't have SSH access**, use cPanel's **phpMyAdmin** instead:
1. Open phpMyAdmin, select your database, go to the **SQL** tab.
2. Run the SQL below (this mirrors exactly what the migrations do) —
   replacing nothing, just paste and run:

```sql
CREATE TABLE admins (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(100) NOT NULL UNIQUE,
  password VARCHAR(255) NOT NULL,
  name VARCHAR(150) NOT NULL,
  created_at DATETIME NULL
);
INSERT INTO admins (username, password, name, created_at) VALUES
('admin', '$2y$10$OwPiYKv8Mv10IZ5IMstReeFDE8sE2ueG1ph6k8QeTTjADu7BzU0zm', 'Administrator', NOW());
-- This hash corresponds to the password "Admin@123" — log in with
-- admin / Admin@123, then change it immediately (see below).

CREATE TABLE events (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(200) NOT NULL,
  slug VARCHAR(220) NOT NULL UNIQUE,
  description TEXT NULL,
  venue VARCHAR(255) NULL,
  event_date DATE NOT NULL,
  start_time TIME NULL,
  end_time TIME NULL,
  status ENUM('upcoming','ongoing','completed','cancelled') NOT NULL DEFAULT 'upcoming',
  created_at DATETIME NULL,
  updated_at DATETIME NULL,
  INDEX (event_date)
);

CREATE TABLE registrations (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  event_id INT UNSIGNED NOT NULL,
  reg_code VARCHAR(20) NOT NULL UNIQUE,
  full_name VARCHAR(150) NOT NULL,
  phone VARCHAR(20) NOT NULL,
  email VARCHAR(150) NULL,
  city VARCHAR(100) NULL,
  profession VARCHAR(100) NULL,
  age_group VARCHAR(20) NULL,
  source ENUM('online','walkin') NOT NULL DEFAULT 'online',
  heard_from VARCHAR(100) NULL,
  checked_in TINYINT(1) NOT NULL DEFAULT 0,
  checked_in_at DATETIME NULL,
  created_at DATETIME NULL,
  UNIQUE KEY event_phone (event_id, phone),
  INDEX (phone),
  INDEX (event_id),
  FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE volunteers (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  reg_code VARCHAR(20) NOT NULL UNIQUE,
  full_name VARCHAR(150) NOT NULL,
  phone VARCHAR(20) NOT NULL UNIQUE,
  email VARCHAR(150) NULL,
  city VARCHAR(100) NULL,
  profession VARCHAR(100) NULL,
  age_group VARCHAR(20) NULL,
  areas VARCHAR(255) NULL,
  about TEXT NULL,
  availability VARCHAR(255) NULL,
  languages VARCHAR(255) NULL,
  agree TINYINT(1) NOT NULL DEFAULT 0,
  created_at DATETIME NULL,
  updated_at DATETIME NULL
);

CREATE TABLE attendance_log (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  registration_id INT UNSIGNED NOT NULL,
  event_id INT UNSIGNED NOT NULL,
  scanned_at DATETIME NOT NULL,
  scanned_by VARCHAR(100) NULL,
  method ENUM('qr','manual') NOT NULL DEFAULT 'qr',
  INDEX (event_id),
  INDEX (registration_id)
);

CREATE TABLE migrations (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  version VARCHAR(255) NOT NULL,
  class VARCHAR(255) NOT NULL,
  `group` VARCHAR(255) NOT NULL,
  namespace VARCHAR(255) NOT NULL,
  time INT NOT NULL,
  batch INT UNSIGNED NOT NULL
);
```

### Setting the admin password (important — do this either way)

Don't rely on the placeholder hash above. Instead, generate a fresh one:

1. On any machine with PHP (or ask your host, or use an online
   "PHP password_hash bcrypt generator" — search for one you trust), run:
   ```php
   <?php echo password_hash('YourNewStrongPassword', PASSWORD_DEFAULT);
   ```
2. Copy the resulting string (starts with `$2y$...`).
3. In phpMyAdmin, either edit the `password` column of the `admin` row you
   just inserted, or run:
   ```sql
   UPDATE admins SET password = 'PASTE_YOUR_HASH_HERE' WHERE username = 'admin';
   ```

If you *do* have SSH/Terminal access, `php spark migrate` handles all of this
automatically and safely — that's the easier path if it's available to you.

## Step 5 — Set folder permissions

The `writable/` folder must be writable by PHP (for sessions, cache, logs).
In cPanel File Manager, right-click `writable` → **Permissions** → set to
`755` (or `775` if your host requires it for group-writable setups). This is
usually fine by default after upload, but check it if you see a
"permission denied" error.

## Step 6 — Visit your site

- Public site: `https://yourdomain.com/`
- Admin panel: `https://yourdomain.com/admin/login`

Log in with the admin username/password you set in Step 4, then immediately
create your first event from **Events → + New Event**.

---

## Everything else (features, how it all works, performance notes)

See `README.md` in this same folder — it documents every feature (QR
registration, walk-in registration, attendance scanning, Excel exports,
volunteer sign-up, and the phone-number-as-unique-key logic) in detail. The
only difference from that file is this one is cPanel/no-Composer specific;
`README.md` assumes a Composer-based install instead, so follow **this**
file for setup and refer to `README.md` for how the app behaves.
