# CodeIgniter 3 to CodeIgniter 4 Migration Report

## 1. Overview

This document describes the migration of the **Admin Students** module from CodeIgniter 3 (CI3) to CodeIgniter 4 (CI4). The module provides student listing and add/edit functionality for the CMM School admin panel.

**Scope of migration:**

- **Students index** – Two list views: Super Admin (all students across schools) and Franchisee (students for the current school), both powered by legacy DataTables server-side endpoints.
- **Students addEdit** – Add/Edit student form with tabbed UI (Student Info, Family, Emergency, Diets, Medications, Forms; and when editing: Activities, Quest, Attendance, Messages, Observations). The **edit** path is fully implemented; the **add** path displays the form but redirects with a “under migration” message on submit until the full add flow is ported.

**Source (CI3):** `application/controllers/admin/students.php`, `application/models/student.php`, and related views under `application/views/admin/`.

**Target (CI4):** `app/Controllers/Admin/Students.php`, `app/Models/StudentModel.php`, and views under `app/Views/admin/`.

---

## 2. Files Migrated

| File Name | Type | Description |
|-----------|------|-------------|
| Students.php | Controller | Admin students: index, listings, addEdit, updateFutureClassData |
| StudentModel.php | Model | Student listing queries, getStudentInfo, getFamilyInfo, setStudentInfoEdit, editDietInfo, editMedicationsInfo, rules |
| Routes.php | Config | Students routes: index, addEdit, studentSuperAdminListing, studentFranchiseeListing |
| studentsSuperAdminList.php | View | Super Admin student list (DataTables) |
| studentsFranchiseeList.php | View | Franchisee student list (DataTables) with ADD button |
| studentsAddEdit.php | View | Main add/edit layout with tabs and form action |
| studentAddEditDefault.php | View | Student Info tab: demographics, program, class, releases, notes |
| studentAddFamily.php | View | Family tab placeholder (add mode) |
| studentAddEmergency.php | View | Emergency contact tab placeholder (add mode) |
| studentMedicationInfo.php | View | Medications tab placeholder (add mode) |

---

## 3. Key Changes from CI3 to CI4

### Namespace usage

- Controllers use `namespace App\Controllers\Admin` and extend `AdminController`.
- Models use `namespace App\Models` and extend `CodeIgniter\Model`.
- References to shared components use `Config\CmmConstants`, `App\Models\UtilityModel`, etc.

### Request / Response handling

- **CI3:** `$this->input->post()`, `$this->uri->segment(4)`, `echo $jsonData`, `redirect()`.
- **CI4:** `$this->request->getPost()`, method parameter `addEdit(?string $editId = null)`, `return $this->response->setJSON([...])`, `return redirect()->to(...)`.

### Model loading

- **CI3:** `$this->load->model('student');` then `$this->student->method()`.
- **CI4:** `model(StudentModel::class)` or `model(UtilityModel::class)`; no loading in constructor.

### Database

- **CI3:** `$this->db->get()`, `$query->result()`, `$query->row()`.
- **CI4:** Query Builder via `$this->db->table(...)`; `->get()->getResult()`, `->getRow()`; `insertBatch()` for batch inserts. Connection via `\Config\Database::connect()` where the controller needs it (e.g. `updateFutureClassData`).

### Validation

- **CI3:** `$this->form_validation->set_rules()`, `$this->form_validation->run()`, `form_error()` in views.
- **CI4:** `$this->validate($rules)` with rules array from `StudentModel::studentsEditRules()`; views use `$validation->getError('field')` and `old('field', $default)`.

### Routing

- **CI3:** Convention-based; segment 4 for addEdit ID.
- **CI4:** Explicit routes in `app/Config/Routes.php`: `students/index`, `students`, `students/addEdit`, `students/addEdit/(:segment)`, and POST routes for listing and addEdit. Specific routes are defined before the generic `students/(:any)` placeholder.

### Session and flash data

- **CI3:** `$this->session->set_flashdata()`, `$this->session->flashdata()`.
- **CI4:** `session()->setFlashdata()`, `session()->getFlashdata()`.

### Views

- **CI3:** `$this->load->view('admin/name', $data)`, `set_value()`, `form_error()`.
- **CI4:** `view('admin/name', $data)` or `$this->layoutView('admin/name')`; `old('key', $default)`, `esc()`, and optional `$validation->getError()`.

---

## 4. Controller Changes

### index()

- **Purpose:** Entry point for the Students module.
- **Behaviour:** Ensures user is allowed (admin or school owner). If in admin mode, shows the Super Admin list view; otherwise shows the Franchisee list view. Sets `header_selected` and `sub_header_selected` for the layout and returns the appropriate view via `layoutView()`.

### studentSuperAdminListing(?string $roster = null)

- **Purpose:** Legacy DataTables server-side endpoint for the Super Admin list.
- **Behaviour:** Reads POST parameters `sEcho`, `iDisplayLength`, `iDisplayStart`, `sSearch`, `iSortCol_0`, `sSortDir_0`. Calls `StudentModel::getStudentsSuperAdminData()` for the current page and for total filtered count. Builds rows (school link, first name, last name, DOB, days enrolled) and returns JSON with `sEcho`, `iTotalRecords`, `iTotalDisplayRecords`, `aaData`. On access failure returns empty JSON.

### studentFranchiseeListing(?string $roster = null)

- **Purpose:** Legacy DataTables server-side endpoint for the Franchisee list.
- **Behaviour:** Same POST contract as above. Uses `StudentModel::getStudentsFranchiseeData()` and `getStudentDailyInOutStatus()`. Builds rows (first name link, last name, class, age string, student type, sign-in/out status, edit link). Returns same JSON shape. On access failure returns empty JSON.

### addEdit(?string $editId = null)

- **Purpose:** Show add/edit form and process edit (and future add) submissions.
- **Behaviour:**
  - **Access:** In admin mode, only SCHOOL_OWNER is allowed; otherwise ADMIN or SCHOOL_OWNER via `ensureAllowed()`.
  - **ID:** Decodes `$editId` from base64 to get `user_id`; empty for add.
  - **POST (edit):** Validates with `studentsEditRules()`. Dispatches by submit type:
    - Medication submit → `editMedicationsInfo()`, redirect with flash.
    - Diet submit → `editDietInfo()`, redirect with flash.
    - Default submit → `setStudentInfoEdit()`, `updateFutureClassData()`, redirect with flash.
  - **POST (add):** Redirects to students index with “Add student is under migration.”
  - **GET:** Loads dropdown data (genders, ethnicities, programs, classes, student types, days, relations, phone types, states) and, when editing, student info, family/emergency, schedules, areas, medications, allergies/diet, status, image path, and formatted start date and DOB. Returns `layoutView('admin/studentsAddEdit')`.

### updateFutureClassData(int $student_id)

- **Purpose:** Keep `student_class_future` in sync with current class and start date.
- **Behaviour:** Loads current `student_class` and `students` row for the given `student_id`. Computes start date and checks for an existing `student_class_future` row for that student, status “registered”, and same date. Inserts or updates the future class record accordingly. Used after main student edit submit.

### ageStringFromDob(string $dob)

- **Purpose:** Build a human-readable age string (e.g. “2 years, 3 months”) from date of birth.
- **Behaviour:** Used only for the Franchisee listing table. Parses DOB, computes age components, and returns a formatted string (or “N/A” / error message).

---

## 5. Database Tables Used

- **users** – User account and modified_at for student/user linkage
- **user_roles** – Role (e.g. STUDENT_ROLE_ID) and status
- **user_addresss** – Address, city, state, zip for student and family
- **user_access_levels** – Access level for student user
- **user_media** – Profile image (for getUserImageName)
- **students** – Core student data (name, DOB, school, type, releases, allergies, diet, etc.)
- **schools** – School name for Super Admin list
- **student_schedules** – Day and start/end time per student
- **days** – Day names/short names
- **student_class** – Current program and class (program_class_type_id)
- **program_class_types** – Class name for listing
- **student_types** – Student type name
- **student_daily_in_out** – Today’s sign-in/out for status column
- **student_medications** – Medications and expiration
- **student_class_future** – Future class registration (updateFutureClassData)
- **parents** – Family and emergency contacts (getFamilyInfo)
- **families** – Family record (getFamilyInfo)
- **relation_with_childs** – Relation label
- **genders** – Gender options
- **ethnicities** – Ethnicity options
- **programs** – Program options
- **student_assignments_status** – Quest tab (getQuestInfo)
- **assignments**, **areas**, **materials**, **concepts**, **lesson_status** – Supporting tables for getQuestInfo
- **states** – State dropdown (country_id = 223)

---

## 6. Features Implemented

- **Student listing (Super Admin)** – Table of all students with school, first name, last name, birthday, days enrolled; server-side search/sort/pagination via legacy DataTables.
- **Student listing (Franchisee)** – Table of current school’s students with first name, last name, class, age, student type, sign-in/out status, and edit link; same DataTables behaviour; ADD button to addEdit.
- **Edit student** – Load student info, family, emergency, schedules, medications, allergies/diet; update student, address, class, schedules; update diet or medications via separate submit buttons.
- **Student Info tab** – Demographics, address, state, zip, DOB, gender, ethnicity, start date, program, class, student type, image upload placeholder, releases (photography, video, social media), notes; Student ID and status when editing.
- **Diets tab** – Allergies and diet restrictions checkboxes; diet submit updates `students.allergic_to` and `diet_restrictions`.
- **Medications tab** – Placeholder in add mode; edit mode uses AJAX (existing JS). Medication submit updates student medications and allergy/diet fields.
- **Family / Emergency / Forms tabs** – Placeholder views for add; edit mode uses existing AJAX-loaded content where implemented.
- **Future class sync** – `updateFutureClassData()` keeps `student_class_future` aligned after student edit.
- **Access control** – Admin mode: SCHOOL_OWNER only; otherwise ADMIN or SCHOOL_OWNER for index and addEdit; listing endpoints return empty data when not allowed.

---

## 7. Security Improvements

- **Prepared queries / Query Builder:** All database access uses the CI4 Query Builder (e.g. `$builder->where()`, `->like()`) so values are bound; search uses `like()` / `orLike()` instead of raw concatenation.
- **Validation:** Edit form uses CI4 validation with `studentsEditRules()` (required fields, lengths, trim).
- **Encoded IDs:** Edit ID in the URL is base64-encoded; decoded only in the controller and validated (e.g. getStudentID) before use.
- **Access checks:** Every public method checks roles (and admin vs franchisee) before returning data or performing updates; listing endpoints return empty JSON when not allowed.
- **Output encoding:** Views use `esc()` for dynamic output where appropriate.
- **No direct $_POST / $_GET:** Input is read via `$this->request->getPost()` and passed as arrays into the model where needed.

---

## 8. Important Methods

### Controller

- **ensureAllowed()** – Inherited from AdminController; ensures user has ADMIN or SCHOOL_OWNER role for admin module.
- **updateFutureClassData($student_id)** – Syncs `student_class_future` with current class and start date after edit.
- **ageStringFromDob($dob)** – Returns age string for Franchisee listing.

### StudentModel

- **getStudentsSuperAdminData(...)** – Query for Super Admin list: users + students + schools + schedules + days; optional date/school filters; search and sort; limit/offset for pagination.
- **getStudentsFranchiseeData(...)** – Query for Franchisee list: current school’s students with class and student type; search and sort; limit/offset.
- **getStudentDailyInOutStatus($studentId)** – Returns today’s sign-in/out or “ABSENT”/“N/A” from `student_daily_in_out`.
- **getStudentID($userID)** – Returns `student_id` for a user_id.
- **getFamilyID($studentUserId)** – Returns `family_id` for a student’s user_id.
- **getStudentInfo($user_id)** – Single row for addEdit: user, address, student, and program/class with explicit column list to avoid overlaps.
- **getFamilyInfo($userId, $userType, $familyUserId)** – Family or emergency contacts for a student (userType `'family'` or `''`).
- **getQuestInfo($studentId, $areasID)** – Data for Quest tab (assignments/areas/materials/concepts).
- **getUniqueUserName($userid)** – Placeholder for unique username (used when add is implemented).
- **studentsEditRules()** – Returns CI4 validation rules array for the edit form.
- **setStudentInfoEdit($user_id, $studentID, array $post)** – Updates users, user_addresss, students, student_class, and replaces student_schedules from POST.
- **editDietInfo($studentID, array $post)** – Updates `allergic_to` and `diet_restrictions` on students.
- **editMedicationsInfo($userId, array $post)** – Updates allergy/diet on students, replaces student_medications rows from POST.

### UtilityModel (existing)

- **getRowsByField()** / **getRowByField()** – Used for dropdowns and single-row lookups.
- **getUserImageName()** – Profile image URL for student.
- **UserDateTime()** / **GmDateTime()** – Timezone-aware date/time for display and storage.

### SecuritiesModel (existing)

- **dateFormate()** – Formats DOB for display.
- **checkAdminMode()** – Determines Super Admin vs Franchisee.
- **allowedRoles()** – Enforces role for addEdit (admin vs franchisee).

---

## 9. Future Improvements

- **Implement full Add flow** – Port `setStudentInfoAdd()` from CI3 (create user, student, family, parents, emergency, schedules, file uploads, email) so new students can be created from the add form.
- **Service layer** – Move multi-table update logic (e.g. setStudentInfoEdit, editMedicationsInfo) into a dedicated service class to keep the controller thin and simplify testing.
- **Repository pattern** – Wrap StudentModel and related reads in a repository for listing and form data to centralize query logic.
- **Stronger validation** – Add rules for diet/medication submits; consider per-tab rule groups and custom rules (e.g. phone format, date ranges).
- **API support** – If the front end will move to a SPA or mobile app, add JSON API endpoints and standardise responses (e.g. JSON:API or a simple REST format).
- **Replace legacy DataTables** – Migrate from the old sEcho/iDisplayLength/aaData protocol to DataTables 1.10+ (draw, start, length, order, search) and align with other migrated list endpoints.
- **File uploads** – Implement image and document upload in addEdit using CI4’s file validation and move/upload helpers.
- **Logging and error handling** – Log validation failures and DB errors; return consistent error messages or codes for listing and addEdit.

---

## 10. Conclusion

The Admin Students module has been migrated from CodeIgniter 3 to CodeIgniter 4 for **index** and **addEdit**. The students list (Super Admin and Franchisee) and the edit-student flow (main submit, diet submit, medication submit) are implemented with the same business rules and UI structure as the original. Add-student currently shows the form but does not create records; the intention is to complete that in a follow-up by porting the full add logic and file/email handling.

All touched code uses CI4 namespaces, request/response, model loading, validation, routing, and views. Database access uses the Query Builder and existing utility and security helpers. Security is improved through validation, encoded edit IDs, role checks, and avoidance of raw input in queries. The migration report and code comments provide a clear basis for future work (add flow, refactors, and API or front-end changes).
