# Moodle Settings Module - Architecture & Workflow Analysis

## Overview
The Moodle Settings module located at `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/` is a feature-rich configuration interface for managing Moodle integration settings. It follows a **Request-Validation-Processing workflow** pattern with permission checks and user-friendly feedback.

---

## Module Structure

### File Inventory
```
Views/Settings/Moodle/
├── index.php          (Entry point & routing)
├── form.php           (Form rendering)
├── validator.php      (Input validation)
├── processor.php      (Data persistence)
├── deny.php           (Access denial UI)
└── breadcrumb.php     (Navigation breadcrumb)
```

---

## File Purposes & Responsibilities

### 1. **index.php** (Entry Point & Controller Logic)
**Location:** `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/index.php`

**Purpose:** Main entry point that acts as a router/dispatcher based on permissions and form submission state.

**Key Responsibilities:**
- Permission checking (singular & plural)
- Authority validation (checks if user is the author of the setting)
- Conditional view rendering based on submission state
- Acts as the application's front controller for this feature

**Key Logic:**
```php
// Lines 38-44: Permission and authority checks
$data['model'] = model("App\Modules\Sie\Models\Sie_Settings");
$data['permissions'] = array(
    'singular' => 'sie-settings-edit',
    "plural" => 'sie-settings-edit-all'
);
$singular = $authentication->has_Permission($data['permissions']['singular']);
$plural = $authentication->has_Permission($data['permissions']['plural']);
$author = $data['model']->getAuthority($oid, safe_get_user());
$authority = ($singular && $author) ? true : false;
$submited = $request->getPost("submited");
```

**Workflow Decision (Lines 51-71):**
- If form is submitted (`$submited` is set): render breadcrumb + validator view
- If form is not submitted: render breadcrumb + form view
- If user lacks permissions: render breadcrumb + deny view

**Output:** JSON response with three sections:
```php
$json = array(
    'breadcrumb' => view($breadcrumb, $data),
    'main' => view($form|$validator|$deny, $data),
    'right' => "",
);
echo(json_encode($json));
```

---

### 2. **form.php** (Form Rendering)
**Location:** `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/form.php`

**Purpose:** Renders the HTML form for editing Moodle configuration settings.

**Key Responsibilities:**
- Load current Moodle settings from database
- Build HTML form fields using the Forms service
- Display setting values for user editing
- Provide submit/cancel buttons

**Key Sections:**

**Service Setup (Lines 4-10):**
```php
$request = service('request');
$bootstrap = service('bootstrap');
$dates = service('dates');
$strings = service('strings');
$authentication = service('authentication');
$server = service("server");
$f = service("forms", array("lang" => "Sie_Settings."));
```

**Data Loading (Lines 27-29):**
Retrieves three Moodle settings from database:
```php
$qtoken = $model->getSetting("MOODLE-TOKEN");    // API token
$qurl = $model->getSetting("MOODLE-URL");        // Moodle base URL
$qcategory = $model->getSetting("MOODLE-CATEGORY"); // Course category
```

**Form Fields (Lines 45-56):**
Creates 6 input fields:
1. **Moodle URL (Name)** - Read-only label
2. **Moodle URL (Value)** - Editable text field
3. **Moodle Token (Name)** - Read-only label
4. **Moodle Token (Value)** - Editable text field
5. **Moodle Category (Name)** - Read-only label
6. **Moodle Category (Value)** - Editable text field
7. **Date** - Auto-populated, read-only
8. **Time** - Auto-populated, read-only
9. **Author** - Hidden field (current user)

Plus Cancel and Submit buttons.

**Field Grouping (Lines 57-63):**
Organizes fields into logical groups with a separator and button group.

**Output:** Bootstrap Card component with form content.

---

### 3. **validator.php** (Input Validation)
**Location:** `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/validator.php`

**Purpose:** Validates form submission input before processing.

**Key Responsibilities:**
- Define validation rules for form fields
- Execute validation checks
- Route to processor on success or back to form with errors on failure

**Validation Rules (Lines 27-31):**
```php
$f->set_ValidationRule("value-moodle-url", "trim|required");
$f->set_ValidationRule("value-moodle-token", "trim|required");
// Note: date, time, author validation is commented out
```

**Two Possible Paths (Lines 33-46):**

**Path A - Validation Success:**
```php
if ($f->run_Validation()) {
    $c = view($component . '\processor', $parent->get_Array());
}
```
Routes to processor.php to save data.

**Path B - Validation Failure:**
```php
else {
    $c = $bootstrap->get_Card('validator-error', array(
        'class' => 'card-danger',
        'text' => lang("App.validator-errors-message"),
        'errors' => $f->validation->listErrors(),
        // ... error card config
    ));
    $c .= view($component . '\form', $parent->get_Array());
}
```
Displays error card + reloads form with user's previous input.

---

### 4. **processor.php** (Data Persistence)
**Location:** `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/processor.php`

**Purpose:** Saves validated form data to the database.

**Key Responsibilities:**
- Prepare setting arrays with metadata (date, time, author)
- Insert or update settings based on existence
- Display success feedback
- Provide navigation options

**Data Preparation (Lines 15-40):**
Creates three setting arrays for the three Moodle settings:

```php
$token = array(
    "setting" => "MOODLE-TOKEN",
    "name" => $f->get_Value("Token de Moodle"),
    "value" => $f->get_Value("value-moodle-token"),
    "date" => service("dates")::get_Date(),
    "time" => service("dates")::get_Time(),
    "author" => safe_get_user(),
);

$url = array(
    "setting" => "MOODLE-URL",
    "name" => $f->get_Value("URL de Moodle"),
    "value" => $f->get_Value("value-moodle-url"),
    // ... metadata
);

$category = array(
    "setting" => "MOODLE-CATEGORY",
    "name" => $f->get_Value("Categoria para los cursos"),
    "value" => $f->get_Value("value-moodle-category"),
    // ... metadata
);
```

**Database Operations (Lines 54-70):**
Uses **upsert pattern** - checks if setting exists, then updates or inserts:

```php
$qtoken = $model->find("MOODLE-TOKEN");
if (is_array($qtoken)) {
    $edittoken = $model->update("MOODLE-TOKEN", $token);
} else {
    $createtoken = $model->insert($token);
}
// Same pattern for URL and CATEGORY
```

**Success Feedback (Lines 72-82):**
Displays success card with:
- Title: `Sie_Settings.edit-success-title`
- Message: `Sie_Settings.edit-success-message`
- Audio feedback: `sie/settings-edit-success-message.mp3`
- Navigation link back to settings list

---

### 5. **deny.php** (Access Control UI)
**Location:** `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/deny.php`

**Purpose:** Displays access denial message when user lacks permissions.

**Key Responsibilities:**
- Detect login status
- Display appropriate denial message (access denied vs. login required)
- Use Bootstrap 5.3.3 styling for consistency

**Two Conditions (Lines 28-54):**

**Condition A - User Logged In But No Permission:**
```php
if ($authentication->get_LoggedIn()) {
    // Display "Access Denied" card with ban icon
    // Offers button to continue to settings list
}
```

**Condition B - User Not Logged In:**
```php
else {
    // Display "Login Required" card with lock icon
    // Offers button to continue to settings list
}
```

**Output:** Bootstrap Card with icon, message, and continue button.

---

### 6. **breadcrumb.php** (Navigation Aid)
**Location:** `/www/wwwroot/_development/app/Modules/Sie/Views/Settings/Moodle/breadcrumb.php`

**Purpose:** Provides consistent navigation breadcrumb across all Moodle settings pages.

**Breadcrumb Path (Lines 25-29):**
```
SIE > Settings > Moodle (active)
```

Hardcoded menu structure:
```php
$menu = array(
    array("href" => "/sie/", "text" => "SIE", "class" => false),
    array("href" => "/sie/settings/home/" . lpk(), "text" => lang("App.Settings"), "class" => false),
    array("href" => "/sie/settings/moodle/" . lpk(), "text" => "Moodle", "class" => "active"),
);
```

---

## Data Model: Sie_Settings

**Table:** `sie_settings`

**Primary Key:** `setting` (string identifier like "MOODLE-TOKEN")

**Fields:**
```php
[
    "setting",      // Unique setting identifier
    "name",         // Human-readable setting name
    "value",        // The actual setting value
    "date",         // Date when last modified
    "time",         // Time when last modified
    "author",       // User who last modified
    "created_at",   // Automatic timestamp (creation)
    "updated_at",   // Automatic timestamp (update)
    "deleted_at",   // Soft delete marker
]
```

**Key Methods:**
- `getSetting($setting)`: Returns cached setting data
- `find($id)`: Returns raw query result
- `insert($data)`: Creates new setting
- `update($id, $data)`: Updates existing setting
- `getAuthority($id, $author)`: Checks if user authored the setting

---

## Complete Workflow / User Journey

### Happy Path (Authorized User with Valid Input):

```
1. User navigates to /sie/settings/moodle/{id}
   ↓
2. index.php executes:
   - Loads Sie_Settings model
   - Checks permissions (singular + plural)
   - Checks authority (is user the author?)
   - Checks if form was submitted
   ↓
3a. IF form NOT submitted:
    - Renders breadcrumb.php
    - Renders form.php (with current settings loaded via getSetting())
    - Returns JSON with form UI
   ↓
3b. User fills form and clicks Submit
    ↓
4. Form POST request received, validator.php executes:
    - Validates "value-moodle-url" (trim|required)
    - Validates "value-moodle-token" (trim|required)
    - Runs validation
    ↓
5a. IF validation passes:
    - Routes to processor.php
    ↓
5b. processor.php executes:
    - Builds three setting arrays with metadata
    - For each setting:
      * Checks if it exists via model->find()
      * If exists: calls model->update()
      * If not exists: calls model->insert()
    - Displays success card with audio feedback
    ↓
6. Success message shown, user can continue
```

### Alternative Path (Invalid Input):

```
4b. validator.php executes validation
    ↓
5b. IF validation FAILS:
    - Displays error card listing all validation errors
    - Re-renders form.php with user's previous input
    - User corrects errors and resubmits
```

### Access Denied Path:

```
2. index.php permission check:
   - User lacks 'sie-settings-edit' permission AND
   - User is not the author (or plural permission missing)
   ↓
3. deny.php renders:
   - If logged in: "Access Denied" message
   - If not logged in: "Login Required" message
   - Button to return to settings list
```

---

## Service Dependencies

The module uses these core services:

| Service | Usage |
|---------|-------|
| **request** | Retrieves POST data (`getPost("submited")`) |
| **bootstrap** | Renders card, form, breadcrumb components |
| **dates** | Gets current date/time for metadata |
| **strings** | (Loaded but not directly used in these files) |
| **authentication** | Permission checks, login status, current user |
| **server** | Gets HTTP referer for "back" link |
| **forms** | Builds and validates form fields |

---

## Language Strings

The module uses language keys with namespace `Sie_Settings.`:

- `Sie_Settings.edit-success-title` - Success page title
- `Sie_Settings.edit-success-message` - Success message text
- `App.validator-errors-message` - Validation error message
- `App.Access-denied-message` - Access denial message
- `App.Access-denied-title` - Access denial title
- `App.login-required-message` - Login required message
- `App.login-required-title` - Login required title
- `App.Cancel` - Cancel button text
- `App.Edit` - Submit button text
- `App.Settings` - Breadcrumb settings link text
- `app/validator-errors-message.mp3` - Audio feedback for errors
- `sie/settings-edit-success-message.mp3` - Audio feedback for success

---

## Interaction Diagram

```
┌─────────────────────────────────────────────────────────────┐
│                    User Browser                              │
│  (Sends request to /sie/settings/moodle/{id})               │
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ↓
┌─────────────────────────────────────────────────────────────┐
│             index.php (Router/Dispatcher)                    │
│  - Checks permissions                                        │
│  - Checks authority                                          │
│  - Detects form submission                                   │
│  - Routes to appropriate view                                │
└──────────┬──────────────┬──────────────────┬────────────────┘
           │              │                  │
      (denied)     (not submitted)      (submitted)
           │              │                  │
           ↓              ↓                  ↓
    ┌──────────┐   ┌──────────┐      ┌──────────────┐
    │ deny.php │   │form.php  │      │validator.php │
    │          │   │          │      │              │
    │Shows     │   │Loads     │      │Validates     │
    │access    │   │settings  │      │input         │
    │message   │   │Renders   │      │              │
    │          │   │HTML form │      │              │
    └──────────┘   │          │      └──┬────────┬──┘
                   │Includes: │         │        │
                   │- URL     │    (pass)  (fail)
                   │- Token   │        │        │
                   │- Category│        ↓        ↓
                   │- Author  │   ┌─────────┐ ┌─────────┐
                   │- Date    │   │processor│ │ form.php│
                   │- Time    │   │  .php   │ │+ errors │
                   └──────────┘   │         │ └─────────┘
                                  │Upserts  │
                                  │data     │
                                  │Displays │
                                  │success  │
                                  └─────────┘
                                      │
                                      ↓
                           ┌─────────────────────┐
                           │ Sie_Settings Model  │
                           │                     │
                           │ find() - check      │
                           │ insert() - create   │
                           │ update() - modify   │
                           │ getSetting() - read │
                           │                     │
                           │ Database: sie_      │
                           │           settings  │
                           └─────────────────────┘
```

---

## Key Design Patterns

### 1. **Request-Validation-Processing (RVP) Pattern**
- **Request**: form.php presents the form
- **Validation**: validator.php checks input
- **Processing**: processor.php persists data

### 2. **Conditional Routing in Entry Point**
index.php decides which view to render based on:
- Permission state (permissions + authority)
- Request state (form submitted or not)

### 3. **Upsert Pattern (Insert or Update)**
processor.php uses:
```php
if (exists) { update } else { insert }
```

### 4. **Service Locator Pattern**
All dependencies obtained via `service()` function (Higgs Framework).

### 5. **JSON Response for AJAX**
index.php returns structured JSON:
```json
{
  "breadcrumb": "...",
  "main": "...",
  "right": ""
}
```

---

## Security Features

1. **Permission Checks** (index.php)
   - Singular permission: `sie-settings-edit`
   - Plural permission: `sie-settings-edit-all`
   - Authority check: Only author can edit

2. **Input Validation** (validator.php)
   - Field sanitization (trim)
   - Required field checks
   - Framework validation rules

3. **Soft Deletes**
   - Model uses soft deletes (`useSoftDeletes = true`)
   - Allows audit trail

4. **Metadata Tracking**
   - Author recorded with each change
   - Date/time logged automatically
   - Prevents unauthorized modifications

---

## Summary Table

| File | Role | Input | Output | Dependencies |
|------|------|-------|--------|--------------|
| **index.php** | Router | POST submited flag | JSON (3 sections) | authentication, model |
| **form.php** | View Layer | model data | HTML form | forms service, model |
| **validator.php** | Validation | POST data | Success→processor or Failure→form | forms service |
| **processor.php** | Business Logic | form data | Success card | model, bootstrap, dates |
| **deny.php** | Access Control | user login state | Denial card | bootstrap, authentication |
| **breadcrumb.php** | Navigation | none | Breadcrumb HTML | bootstrap |

---

## Notes & Observations

1. **Three-Setting Configuration**: The module manages exactly three Moodle settings (token, URL, category), each following the same upsert pattern.

2. **Hardcoded Settings**: Setting names are hardcoded ("MOODLE-TOKEN", "MOODLE-URL", "MOODLE-CATEGORY") - not dynamic.

3. **Metadata on Every Save**: Date, time, and author are always captured, creating an audit trail.

4. **Language Abstraction**: All user-facing text goes through `lang()` function, enabling multi-language support.

5. **Audio Feedback**: Success and error messages include MP3 audio files for accessibility.

6. **Cached Queries**: Sie_Settings extends CachedModel4, so getSetting() uses caching for performance.

7. **Bootstrap Integration**: Extensively uses Bootstrap service for UI components (cards, forms, breadcrumbs).

8. **AJAX-Ready**: JSON output suggests this is called via AJAX from a parent SPA or dashboard.

---

## Related Files (Outside This Module)

- **Model**: `/www/wwwroot/_development/app/Modules/Sie/Models/Sie_Settings.php`
- **Language Files**: `app/Language/es/Sie_Settings.php` and `app/Language/en/Sie_Settings.php`
- **Database**: `sie_settings` table in authentication database
- **Routes**: Likely defined in Sie module routes config

